hdu3037(lucas定理)

时间:2024-01-09 15:01:08

给定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)

hdu3037(lucas定理)

其中C(n,k)=C(n-1,k)+C(n-1,k-1) 的意思是从n个数中取出k个的组合,  那么对于一个数来说,它要么不取,转为C(n-1,k), 要么取转为C(n-1,k-1)

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
typedef long long LL;
const int INF = <<;
/* */ LL fact[]; LL pow(LL a, LL k, LL p)
{
LL ret = ;
while (k)
{
if (k & )
ret = ret * a %p;
a = a * a % p;
k >>= ;
}
return ret;
}
LL C(LL n, LL m, LL p)
{
if (n < m || m < ) return ;
LL a = fact[n], b = fact[n - m] * fact[m] % p;
return a * pow(b, p - , p) % p;
}
LL lucas(int n, int m, int p)
{
if (m == ) return ;
return C(n%p, m%p,p) * lucas(n / p, m / p, p) % p;
}
int main()
{
int t, n, m, p;
scanf("%d", &t);
while (t--)
{
scanf("%d%d%d", &n, &m, &p);
fact[] = ;
for (int i = ; i <= p; ++i)
fact[i] = fact[i - ] * i % p;
printf("%I64d\n", lucas(n + m, n, p)); }
return ;
}