codeforce 258#E(lucas+容斥+组合)

来源:互联网 发布:淘宝模板 编辑:程序博客网 时间:2024/04/29 09:07

CF 451E

#include<iostream>#include<cstring>#include<cstdio>using namespace std;typedef long long ll;const ll mod=1000000007;ll qpow(ll a,ll b,ll p){    ll ans=1;    while(b){        if(b&1) ans=(ans*a)%p;        a=(a*a)%p;        b>>=1;    }    return ans;}ll C(ll m,ll n,ll p){    if(n>m) return 0;    if(m-n<n) n=m-n;    ll s1=1,s2=1;    for(ll i=0;i<n;i++){        s1=s1*(m-i)%p;        s2=s2*(i+1)%p;    }    return s1*qpow(s2,p-2,p)%p;}ll lucas(ll m,ll n ,ll p)     //求C(m,n) mod p{    if(!n) return 1;    return C(m%p,n%p,p)*lucas(m/p,n/p,p)%p;}/*数论Lucas定理是用来求 c(n,m) mod p的值,p是素数(从n取m组合,模上p)。描述为:Lucas(n,m,p)=cm(n%p,m%p)* Lucas(n/p,m/p,p)Lucas(x,0,p)=1;而<费马小定理p为素数, a^(p-1)=1(mod p)->a^(p-2)=a^-1(mod p)->a^(p-2)是a mod p的逆;cm(a,b)%p==a! / (b!*(a-b)!) mod p==a! * (b!*(a-b)!)^(p-2) mod p也= (a!/(a-b)!) * (b!)^(p-2)) mod p这里,其实就是直接求 (a!/(a-b)!) / (b!) mod p由于 (a/b) mod p = a * b^(p-2) mod p*/int n;ll s,f[25];ll solve(){    ll ans=0;    for(int i=0;i<(1<<n);i++){     //2^n枚举,即二进制枚举;        ll sign=1,sum=s;        for(int j=0;j<n;j++){            if(i&(1<<j)){                sum-=f[j]+1;                sign*=-1;            }        }        if(sum<0) continue;        ans+=sign*lucas(sum+n-1,n-1,mod);  //容斥原理        ans%=mod;    }    return (ans+mod)%mod;}int main(){    while(scanf("%d%I64d",&n,&s)!=EOF)    {        for(int i=0;i<n;i++)            scanf("%I64d",f+i);        printf("%I64d\n",solve());    }    return 0;}


0 0
原创粉丝点击