CodeForces - 451E Devu and Flowers【簡單容斥】
阿新 • • 發佈:2018-12-18
題意:給N個數(a1,a2……an)和一個S,求(b1+b2+……+bn)==S的方案數,其中0<=bi<=ai;
分析:題意很簡單,考慮容斥。
其中U為全集,t為U的i元組。
由於N<=20,直接二進位制列舉即可,s很大,考慮使用lucas優化。
#include <bits/stdc++.h> using namespace std; const int mod = 1e9+7; long long f[30]; long long qk(long long a,long long n) { long long ans=1; while(n){ if(n&1)ans=ans*a%mod; a=a*a%mod; n>>=1; } return ans; } long long c(long long a,long long b) { if(a==b)return 1; if(a<b)return 0; long long up=1,dw=1; for (int i = a-b+1; i <= a; ++i) { up=up*i%mod; } for (int i = 2; i <= b; ++i) { dw=dw*i%mod; } return up*qk(dw,mod-2)%mod; } long long lucas(long long a,long long b) { if(a<mod&&b<mod) { return c(a,b); } else { return (c(a%mod,b%mod)*lucas(a/mod,b/mod))%mod; } } int main () { long long n,s; long long ans=1; cin>>n>>s; for (int i = 0; i < n; ++i) { scanf("%lld",&f[i]); } ans=lucas(s+n-1,n-1);//總方案數 int len=1<<n; //二進位制列舉,減去不合法方案 for (int i = 1; i < len; ++i) { long long sum=0; long long cnt=0; for (int j = 0; j < n; ++j) { int x=1<<j; if(x&i) { cnt++; sum+=f[j]+1; } } if(cnt&1) { ans=(ans-lucas(s-sum+n-1,n-1)+mod)%mod; } else { ans=(ans+lucas(s-sum+n-1,n-1))%mod; } } printf("%lld\n",ans); }