Atcoder Beginner Contest 156E(隔板法,组合数学)
1 #define HAVE_STRUCT_TIMESPEC 2 #include<bits/stdc++.h> 3 using namespace std; 4 const int N = 5e5 + 7; 5 const long long mod=1e9+7; 6 long long fac[N],inv[N]; 7 long long qpow(long long a,long long b){ 8 long long ans=1; 9 while(b){ 10 if(b&1) 11 ans=a*ans%mod; 12 b>>=1; 13 a=a*a%mod; 14 } 15 return ans; 16 } 17 void P(){ 18 fac[0]=1; 19 for(int i=1;i<N;i++) 20 fac[i]=fac[i-1]*i%mod; 21 inv[N-1]=qpow(fac[N-1],mod-2); 22 for(int i=N-2;i>=0;i--) 23 inv[i]=inv[i+1]*(i+1)%mod; 24 } 25 long long C(int a,int b){ 26 return fac[a]*inv[b]%mod*inv[a-b]%mod; 27 } 28 int n,k; 29 int main() { 30 ios::sync_with_stdio(false); 31 cin.tie(NULL); 32 cout.tie(NULL); 33 P(); 34 cin>>n>>k; 35 if(k>=n)//如果k>=n的话,所有1都可以移动,相当于n个相同球放到n个相同盒中,盒子可以空。 36 cout<<C(n+n-1,n-1);//n个球和n个盒子总共有2n-1个空隙,把n个盒子插到空隙里,即为C(2n-1,n)=C(2n-1,n-1) 37 else{ 38 long long tot=C(2*n-1,n-1); 39 for(int i=1;i<n-k;i++){//n-k个位置至少为1,容斥减去不足n-k个位置至少为1的情况 40 tot-=1ll*C(n,i)*C(n-1,i-1)%mod;//n个球放到i个盒子里,每个盒子都不为空 41 //先从n个盒子里选出i个盒子,然后n个球之间存在n-1个空隙,把i-1块挡板插到n-1个空隙里,就可以把n个球分为i份且每一份都不为空 42 tot+=mod; 43 tot%=mod; 44 } 45 cout<<tot<<'\n'; 46 } 47 return 0; 48 }
保持热爱 不懈努力
不试试看怎么知道会失败呢(划掉)
世上无难事 只要肯放弃(划掉)