题意:求在n棵树上摘不超过m颗豆子的方案数,结果对p取膜。
思路:其实就相当于把i(0 <= i <= m)个球放入n个不同的盒子里,盒子可以为空。
很明显,需要用到隔板法。所以对于i个球,方案数为C(i+n-1, n-1)。
总方案数为C(n-1, n-1)+C(n, n-1)+...+C(n+m-1, n-1);
然后根据公式C(n, m) = C(n, n-m)得方案数为
C(n-1, 0)+C(n, 1)+...+C(n+m-1, m);
然后再根据公式C(n, m) = C(n-1, m)+C(n-1, m-1)得方案数为
0+C(n-1, 0)+C(n, 1)+...+C(n+m-1, m)
= C(n, 0)+C(n, 1)+C(n+1, 2)+...+C(n+m-1, m)
= C(n+m, m)
此时方案数变为了C(n+m, m)%p;
思路:其实就相当于把i(0 <= i <= m)个球放入n个不同的盒子里,盒子可以为空。
很明显,需要用到隔板法。所以对于i个球,方案数为C(i+n-1, n-1)。
总方案数为C(n-1, n-1)+C(n, n-1)+...+C(n+m-1, n-1);
然后根据公式C(n, m) = C(n, n-m)得方案数为
C(n-1, 0)+C(n, 1)+...+C(n+m-1, m);
然后再根据公式C(n, m) = C(n-1, m)+C(n-1, m-1)得方案数为
0+C(n-1, 0)+C(n, 1)+...+C(n+m-1, m)
= C(n, 0)+C(n, 1)+C(n+1, 2)+...+C(n+m-1, m)
= C(n+m, m)
此时方案数变为了C(n+m, m)%p;
由于n+m和m较大,且p比n+m和m小,且p为素数,所以这儿用Lucas定理求解即可。
Code1:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
int N, M, P;
LL quickM(LL a, LL b, LL p)
{
LL ans = 1, base = a;
while(b)
{
if(b&1) ans = ans*base%p;
base = base*base%p;
b >>= 1;
}
return ans;
}
LL C(LL n, LL m, LL p)
{
if(n < m) return 0;
if(n == m) return 1;
if(m > n-m) m = n-m;
LL fta = 1, ftb = 1;
for(LL i = 0; i < m; ++i)
{
fta = fta*(n-i)%p;
ftb = ftb*(m-i)%p;
}
return fta*quickM(ftb, p-2, p)%p;
}
LL Lucas(LL n, LL m, LL p)
{
LL ans = 1;
while(n && m && ans)
{
ans = ans*C(n%p, m%p, p)%p;
n /= p; m /= p;
}
return ans;
}
int main()
{
int t;
scanf("%d", &t);
for(int _ = 1; _ <= t; ++_)
{
scanf("%d %d %d", &N, &M, &P);
printf("%lld\n", Lucas(N+M, M, P));
}
return 0;
}
Code2:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 100000;
int N, M, P;
LL fact[maxn+5], fiv[maxn+5], inv[maxn+5];
void init()
{
fact[0] = fact[1] = 1;
fiv[0] = fiv[1] = 1;
inv[1] = 1;
for(int i = 2; i <= maxn; ++i)
{
fact[i] = fact[i-1]*i%P;
inv[i] = (-P/i+P)*inv[P%i]%P;
fiv[i] = inv[i]*fiv[i-1]%P;
}
}
LL Lucas(LL n, LL m, LL p)
{
LL ans = 1;
while(n && m && ans)
{
ans = ans*fact[n%p]%p*fiv[(n%p-m%p+p)%p]*fiv[m%p]%p;
n /= p; m /= p;
}
return ans;
}
int main()
{
int t;
scanf("%d", &t);
for(int _ = 1; _ <= t; ++_)
{
scanf("%d %d %d", &N, &M, &P); init();
printf("%lld\n", Lucas(N+M, M, P));
}
return 0;
}
继续加油~