[BJWC2008] Gate Of Babylon

题目链接

容斥+隔板法+Lucas定理

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;

int n,m,t,mod,ans;
int fc[N],fv[N],b[15];

int lucas(int n,int m) {
    if(m<0||m>n) return 0;
    if(n<mod&&m<mod) return 1LL*fc[n]*fv[m]*fv[n-m]%mod;
    return 1LL*lucas(n/mod,m/mod)*lucas(n%mod,m%mod)%mod;
}

void dfs(int x,int sum,int cnt) {
    if(sum>m) return;
    if(x>t) {
        if(cnt&1) ans=(ans-lucas(m-sum+n,n)+mod)%mod;
        else ans=(ans+lucas(m-sum+n,n))%mod;
        return;
    }
    dfs(x+1,sum+b[x]+1,cnt+1);
    dfs(x+1,sum,cnt);
}

int main() {
    scanf("%d%d%d%d",&n,&t,&m,&mod);
    fc[0]=fc[1]=fv[0]=fv[1]=1;
    for(int i=2; i<mod; ++i) fv[i]=1LL*fv[mod%i]*(mod-mod/i)%mod;
    for(int i=2; i<mod; ++i) fv[i]=1LL*fv[i-1]*fv[i]%mod,fc[i]=1LL*fc[i-1]*i%mod;
    for(int i=1; i<=t; ++i) scanf("%lld",b+i);
    dfs(1,0,0); printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/nosta/p/11028257.html