题意:从n个数中选k个数,问有多少种排列与标准k项串恰好有x个位置相同。
标程:
1 #include<cstdio> 2 using namespace std; 3 typedef long long ll; 4 const int mod=1e9+7; 5 const int N=1000005; 6 int n,k,x,ans,jc[N],inv[N],nk; 7 int c(int n,int m) {return (ll)jc[n]*inv[m]%mod*inv[n-m]%mod;} 8 int p(int n,int m) {return (ll)jc[n]*inv[m]%mod;} 9 int main() 10 { 11 scanf("%d%d%d",&n,&k,&x); 12 jc[0]=jc[1]=inv[0]=inv[1]=1; 13 for (int i=2;i<=n;i++) jc[i]=(ll)jc[i-1]*i%mod,inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod; 14 for (int i=1;i<=n;i++) inv[i]=(ll)inv[i]*inv[i-1]%mod; 15 nk=k-x;n-=x; 16 for (int i=0;i<=nk;i++) 17 { 18 int t=(ll)c(nk,i)*p(n-i,n-nk)%mod; 19 if (i&1) ans=((ll)ans-t+mod)%mod;else ans=((ll)ans+t)%mod; 20 } 21 printf("%d ",(ll)ans*c(k,x)%mod); 22 return 0; 23 }
题解:容斥
不妨设标准答案是1 2 3 4 ... k。与标准答案x个位置对应的方式有(k,x)种,每一种的贡献都是一样的。只考虑其中一种,即是求剩下k-x个元素的错排,直接容斥。最后*(k,x)。