标签:help sans esc 求和 contains not lucas定理 tput sam
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5761 Accepted Submission(s):
2310
/* 题目相当于求n个数的和不超过m的方案数。 如果和恰好等于m,那么就等价于方程x1+x2+...+xn = m的解的个数,利用插板法可以得到方案数为: (m+1)*(m+2)...(m+n-1) = C(m+n-1,n-1) = C(m+n-1,m) 现在就需要求不大于m的,相当于对i = 0,1...,m对C(n+i-1,i)求和,根据公式C(n,k) = C(n-1,k)+C(n-1,k-1)得 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,其中p是素数。 然后利用Lucas定理的模板就可以轻松的求得C(n+m,m) % p的值 */ #include<iostream> #include<cstdio> #include<cstring> #define N 100007 using namespace std; long long f[N]; long long Mi(long long a,long long b,long long p) { long long res=1; while(b) { if(b&1) res=res*a%p; b>>=1;a=a*a%p; }return res; } long long C(long long n,long long m,long long p) { if(m>n)return 0; return f[n]*Mi(f[m]*f[n-m]%p,p-2,p)%p; } long long Lcs(long long n,long long m,long long p) { if(m==0)return 1; return (C(n%p,m%p,p)*Lcs(n/p,m/p,p))%p; } int main() { long long n,m,p;long long t; cin>>t; while(t--) { cin>>n>>m>>p; f[0]=1; for(long long i=1;i<=p;i++) f[i]=f[i-1]*i%p; printf("%lld\n",Lcs(n+m,m,p)); } return 0; }
标签:help sans esc 求和 contains not lucas定理 tput sam
原文地址:http://www.cnblogs.com/L-Memory/p/7352542.html