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
",ans); 
66     }
67 }
原文地址:https://www.cnblogs.com/qzqzgfy/p/5577033.html