Light OJ 1095 Arrange the Numbers(容斥)
给定n,m,k,要求在n的全排列中,前m个数字中恰好有k个位置不变,有几种方案?
首先,前m个中k个不变,那就是C(m,k),然后利用容斥原理可得
ans=ΣC(m,k)*(-1)^i*C(m-k,i)*(n-k-i)! (0<=i<=m-k)
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #define ll long long 7 const ll Mod=1000000007; 8 int n,m,k; 9 ll jc[200005],jcny[200005]; 10 int read(){ 11 int t=0,f=1;char ch=getchar(); 12 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 13 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 14 return t*f; 15 } 16 void exgcd(ll a,ll b,ll &x,ll &y){ 17 if (b==0){ 18 x=1; 19 y=0; 20 return; 21 } 22 exgcd(b,a%b,x,y); 23 ll t=x; 24 x=y; 25 y=t-(a/b)*y; 26 } 27 void init(){ 28 jc[1]=1;jc[0]=1;jcny[0]=1; 29 for (int i=2;i<=1000;i++) 30 jc[i]=(jc[i-1]*i)%Mod; 31 ll x,y; 32 exgcd(jc[1000],Mod,x,y); 33 jcny[1000]=x%Mod; 34 for (int i=1000-1;i>=1;i--) 35 jcny[i]=(jcny[i+1]*(i+1))%Mod; 36 } 37 ll powit(ll x,ll y){ 38 ll res=1; 39 while (y){ 40 if (y%2) res=(res*x)%Mod; 41 x=(x*x)%Mod; 42 y/=2; 43 } 44 return res; 45 } 46 ll C(int n,int m){ 47 if (m==0) return 1; 48 return ((((jc[n]%Mod)*(jcny[n-m]%Mod))%Mod)*jcny[m])%Mod; 49 } 50 ll A(int x){ 51 if (x==0) return 1; 52 return jc[x]%Mod; 53 } 54 int main(){ 55 init(); 56 int Tcase=0; 57 int T=read(); 58 while (T--){ 59 printf("Case %d: ",++Tcase); 60 n=read(),m=read(),k=read(); 61 ll ans=0%Mod; 62 for (int i=0;i<=m-k;i++) 63 ans=(ans+powit((ll)-1,(ll)i)*A(n-k-i)*C(m-k,i)+Mod)%Mod; 64 ans=(ans*C(m,k))%Mod; 65 printf("%lld\n",ans); 66 } 67 }