HDU 3037 - Saving Beans (Lucas定理)

题意

有n个树。现在不能收获超过k个豆子,问有几种方法。

思路

问题等价于求出 $x_1 + x_2 … + x_n = k$的非负整数解的个数。

思路有点神奇。

用隔板法,得出:
当收获k个豆子时,答案为$C_{n+k-1}^{k}$
所以最终的答案为$C_{n-1}^0 + C_n^1 + … + C_{n+m-1}^m$

因为$C_n^k = C_{n-1}^k + C_{n-1}^{k-1}$。

然后合并,最后答案就是$C_{n+m-1}^m$

然后用一下Lucas定理。。

代码

LL Extend_GCD(LL a, LL b, LL &d, LL &x, LL &y)
{
    if (!b) { d = a, x = 1, y = 0; }
    else
    {
        Extend_GCD(b, a%b, d, y, x);
        y -= x * (a/b);
    }
}
 
LL inv(LL a, LL p)
{
    LL d, x, y;
    Extend_GCD(a, p, d, x, y);
    return (x+p) % p;
}
 
LL C(LL n, LL m, LL p)
{
    LL ret = 1, a = 1, b = 1;
    while (m)
    {
        a = a*n%p;
        b = b*m%p;
        n--, m--;
    }
    return a * inv(b, p) % p;
}
 
LL Lucas(LL n, LL m, LL p)
{
    if (m == 0) return 1;
    return C(n%p, m%p, p) * Lucas(n/p, m/p, p)%p;
}
 
int main()
{
    //ROP;
    int T;
    cin >> T;
    while (T--)
    {
        LL n, m, p;
        cin >> n >> m >> p;
        cout << Lucas(m+n, n, p) << endl;
    }
    return 0;
}

Powered by Jekyll and Theme by solid