1. 程式人生 > >Codeforces 451 E. Devu and Flowers(組合數學,數論,容斥原理)

Codeforces 451 E. Devu and Flowers(組合數學,數論,容斥原理)

傳送門

解題思路:

假如只有 s 束花束並且不考慮 f ,那麼根據隔板法的可重複的情況時,這裡的答案就是

假如說只有一個 f 受到限制,其不合法時一定是取了超過 f 的花束

那麼根據組合數,我們仍然可以算出其不合法的解共有:

最後,由於根據容斥,減兩遍的東西要加回來,那麼含有偶數個 f 的項為正,奇數個時為負。

答案就是:

搜尋答案,使用Lucas定理,計算組合數上下約去。

程式碼:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 typedef long
long lnt; 5 const lnt mod=(lnt)(1e9+7); 6 int n; 7 lnt s,ans; 8 lnt f[1000]; 9 lnt ksm(lnt x,lnt y) 10 { 11 lnt ans=1; 12 while(y) 13 { 14 if(y&1) 15 ans=ans*x%mod; 16 x=x*x%mod; 17 y=y/2; 18 } 19 return ans; 20 } 21 lnt Lucas(lnt n,lnt m)
22 { 23 if(n<mod&&m<mod) 24 { 25 if(n<m) return 0; 26 if(n==m)return 1; 27 if(m==0)return 1; 28 lnt nj=1,mj=1; 29 lnt a=n-m,b=m; 30 if(a>b) 31 std::swap(a,b); 32 lnt i=b+1; 33 while(i<=n)
34 { 35 nj=(nj*i)%mod; 36 i++; 37 } 38 i=2; 39 while(i<=a) 40 { 41 mj=(mj*i)%mod; 42 i++; 43 } 44 return ksm(mj,mod-2)*nj%mod; 45 } 46 return Lucas(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod; 47 } 48 lnt dle(lnt x) 49 { 50 return (((1&x)^1)<<1)-1; 51 } 52 void dfs(int p,int l,lnt sum) 53 { 54 if(p==n+1) 55 { 56 ans=(ans+dle(l)*Lucas(s-sum+n-1,n-1))%mod; 57 return ; 58 } 59 dfs(p+1,l,sum); 60 dfs(p+1,l+1,sum+f[p]+1); 61 return ; 62 } 63 int main() 64 { 65 scanf("%d%I64d",&n,&s); 66 for(int i=1;i<=n;i++) 67 scanf("%I64d",&f[i]); 68 ans=0; 69 dfs(1,0,0); 70 printf("%I64d\n",(ans%mod+mod)%mod); 71 return 0; 72 }