[xdoj1158]阶乘求逆元(常用于求组合数)
http://acm.xidian.edu.cn/problem.php?id=1158
解题关键:此题注意将$\sum\limits_{i = 0}^x {C_x^iC_y^{i + k}}$转化为$C_{x + y}^{x + k}$
利用二项式定理,
一方面,
${(1 + a)^y}{(1 + \frac{1}{a})^x}$的${a^k}$项的系数,第一个二项式的${a^j}$的系数$C_y^j$,第二个二项式的${a^{ - i}}$系数为$C_x^i$,令$j - i = k$,$j = i + k$,即$\sum\limits_{i = 0}^x {C_x^iC_y^{i + k}}$
另一方面,
${(1 + a)^y}{(1 + \frac{1}{a})^x} = {(1 + a)^{x + y}}{a^{ - x}}$,此时${a^k}$项的系数为$C_{x + y}^{x + k}$,得证。
1、打表
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll mod=1e9+7; 5 ll x,y,k; 6 ll fac[2000005],inv[2000005]; 7 8 ll mod_pow(ll x,ll n,ll mod){ 9 ll res=1; 10 while(n){ 11 if(n&1) res=res*x%mod; 12 n>>=1; 13 x=x*x%mod; 14 } 15 return res; 16 } 17 18 ll Inv(ll x){ 19 return mod_pow(x,mod-2,mod); 20 } 21 22 int main(){ 23 fac[1]=1; 24 for(int i=2;i<=2000000;i++) fac[i]=fac[i-1]*i%mod;//预处理一下,阶乘 25 inv[2000000]=mod_pow(fac[2000000],mod-2,mod);//Fac[N]^{MOD-2} 26 for(int i=2000000-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod; 27 28 29 while(~scanf("%lld%lld%lld",&x,&y,&k)){ 30 if(y==k) printf("1\n"); 31 else if(y<k) printf("0\n"); 32 // else printf("%lld\n",fac[x+y]*inv(fac[x+k])%mod*inv(fac[y-k])%mod); 33 else printf("%lld\n",(fac[x+y]%mod*inv[x+k]%mod*inv[y-k]%mod+mod)%mod); 34 } 35 return 0; 36 }
2、打表+逆元实现
为什么是$n{!^{\bmod - 2}}$
$n{!^{p - 2}}*n! = n{!^{p - 1}} = 1\bmod {\rm{ p;}}$(费马小定理)p为质数,此题中即为mod
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const ll mod=1e9+7; 5 ll x,y,k; 6 ll fac[2000005],inv[2000005]; 7 8 ll mod_pow(ll x,ll n,ll mod){ 9 ll res=1; 10 while(n){ 11 if(n&1) res=res*x%mod; 12 n>>=1; 13 x=x*x%mod; 14 } 15 return res; 16 } 17 18 ll Inv(ll x){ 19 return mod_pow(x,mod-2,mod); 20 } 21 22 int main(){ 23 fac[1]=1; 24 for(int i=2;i<=2000000;i++) fac[i]=fac[i-1]*i%mod;//预处理一下,阶乘 25 //inv[2000000]=mod_pow(fac[2000000],mod-2,mod);//Fac[N]^{MOD-2} 26 //for(int i=2000000-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod; 27 28 29 while(~scanf("%lld%lld%lld",&x,&y,&k)){ 30 if(y==k) printf("1\n"); 31 else if(y<k) printf("0\n"); 32 else printf("%lld\n",fac[x+y]*Inv(fac[x+k])%mod*Inv(fac[y-k])%mod); 33 //else printf("%lld\n",(fac[x+y]%mod*inv[x+k]%mod*inv[y-k]%mod+mod)%mod); 34 } 35 return 0; 36 }