[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;
}
posted @ 2019-06-15 17:32  nosta  阅读(141)  评论(0编辑  收藏  举报