算法提高-集合选取
#include<bits/stdc++.h> using namespace std; long long facc[1000001]={0},fac[1000001]={0},inv[1000001]={0}; long long mod=1000000007; long long pow_mod(int x,int y,int c){ if(y==0) return 1; long long q=pow_mod(x,y/2,c)%c; if(y&1) return (q*q*x)%c; else return (q*q)%c; } //只能用线性求逆的方法,并且递推阶乘的逆 long long C2(int m,int n){ //因为 n!%p的逆 = n!的逆%p,因为是模几逆 return fac[m]*facc[n]%mod*facc[m-n]%mod; } int main() { long long n,k,flag,ans=0,p=1; cin>>n>>k; fac[0]=facc[0]=fac[1]=facc[1]=inv[1]=1; for(int i=2;i<=n;i++){ inv[i]=(mod-mod/i)*inv[mod%i]%mod; fac[i]=fac[i-1]*i%mod; facc[i]=facc[i-1]*inv[i]%mod; } flag=(n-k)%2==0?1:-1; // 倒着算因为牵扯到取模,对后面的值进行递推,如果是正着就要除法,麻烦; for(int i=n;i>=k;i--){ ans=(ans+mod+flag*C2(i,k)*C2(n,i)%mod*p%mod)%mod;//因为flag可能是负值 flag=-flag; p=((p+1)*(p+1)-1)%mod; } cout<<ans<<endl; // cout<<C2(4,2)<<endl; return 0; }