2018 ACM-ICPC 青島站 L ZOJ 4069 容斥+列舉+組合計數
阿新 • • 發佈:2018-11-08
//https://paste.ubuntu.com/p/727RRrKPn7/ #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+5; const ll mod=1e9+7; ll fact[maxn],fact_inv[maxn],pow_2_inv[maxn],inv[maxn],ans; void init() { fact[0]=fact[1]=fact_inv[0]=fact_inv[1]=inv[0]=inv[1]=pow_2_inv[0]=1;; for(int i=2;i<maxn;i++) { inv[i]=(mod-mod/i)*inv[mod%i]%mod; fact[i]=fact[i-1]*i%mod; fact_inv[i]=fact_inv[i-1]*inv[i]%mod; } for(int i=1;i<maxn;i++) pow_2_inv[i]=pow_2_inv[i-1]*inv[2]%mod; } int main() { init(); int t,n,m; scanf("%d",&t); while(t--&&scanf("%d%d",&n,&m)!=EOF) { if(m>n) printf("0\n"); else if(m==n) printf("%lld\n",fact[n-1]*inv[2]%mod); else { ans=0; for(int i=min(n-m,m);i>=0;--i) ans=(ans+(i&1?mod-1:1)*fact[n-m]%mod*fact_inv[n-m-i]%mod*fact_inv[i]%mod*fact[n-1-i]%mod*fact_inv[n-m-1]%mod*fact_inv[m-i]%mod*pow_2_inv[i]%mod)%mod; printf("%lld\n",ans*fact[n]%mod*fact_inv[n-m]%mod); } } return 0; }