给定n,m,p 表示<=m个豆子放在n棵树上,一共有多少种方案数, 总的方案书mod p
如果将m个豆子放在n棵树上, 可以使用插板法
得到方案数是C(n+m-1,n-1)
那么将0<=i<=m个豆子放在n棵上的方案数是 C(n+i-1,n-1)
即
其中C(n,k)=C(n-1,k)+C(n-1,k-1) 的意思是从n个数中取出k个的组合, 那么对于一个数来说,它要么不取,转为C(n-1,k), 要么取转为C(n-1,k-1)
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <algorithm> 5 #include <iostream> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <string> 12 #include <math.h> 13 using namespace std; 14 #pragma warning(disable:4996) 15 typedef long long LL; 16 const int INF = 1<<30; 17 /* 18 19 */ 20 21 LL fact[100001]; 22 23 LL pow(LL a, LL k, LL p) 24 { 25 LL ret = 1; 26 while (k) 27 { 28 if (k & 1) 29 ret = ret * a %p; 30 a = a * a % p; 31 k >>= 1; 32 } 33 return ret; 34 } 35 LL C(LL n, LL m, LL p) 36 { 37 if (n < m || m < 0) return 0; 38 LL a = fact[n], b = fact[n - m] * fact[m] % p; 39 return a * pow(b, p - 2, p) % p; 40 } 41 LL lucas(int n, int m, int p) 42 { 43 if (m == 0) return 1; 44 return C(n%p, m%p,p) * lucas(n / p, m / p, p) % p; 45 } 46 int main() 47 { 48 int t, n, m, p; 49 scanf("%d", &t); 50 while (t--) 51 { 52 scanf("%d%d%d", &n, &m, &p); 53 fact[0] = 1; 54 for (int i = 1; i <= p; ++i) 55 fact[i] = fact[i - 1] * i % p; 56 printf("%I64d\n", lucas(n + m, n, p)); 57 58 } 59 return 0; 60 }