1. 程式人生 > >bzoj 1272: [BeiJingWc2008]Gate Of Babylon

bzoj 1272: [BeiJingWc2008]Gate Of Babylon

esp inline stdout 需要 con mat 一次 printf 範圍

Description

技術分享圖片
技術分享圖片

Solution

如果沒有限制,答案就是 \(\sum_{i=0}^{m}C(n+i-1,i)\)
表示枚舉每一次取的個數,且不超過 \(m\),方案數為可重組合
發現這個東西可以用楊輝三角合並,最終變成 \(C(n+m,m)\)

考慮有限制的情況,直接容斥一下即可,要使得一種物品不合法,我們先強制給他選 \(B_i+1\) 個,剩下的隨意選
此題求組合數需要用 \(Lucas\)

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,T,m,mod,a[20],ans=0,Fac[N],inv[N];
inline
int C(int a,int b){ if(a<b)return 0; return 1ll*Fac[a]*inv[b]*inv[a-b]%mod; } inline int lucas(int a,int b){ if(a<0 || b<0 || a<b)return 0; if(a<mod && b<mod)return C(a,b); return 1ll*lucas(a/mod,b/mod)*C(a%mod,b%mod)%mod; } inline void dfs(int x,int o,int t){ if
(x==T+1){ ans=(ans+o*lucas(n+m-t,m-t))%mod; return ; } dfs(x+1,-o,t+a[x]+1); dfs(x+1,o,t); } int main(){ freopen("pp.in","r",stdin); freopen("pp.out","w",stdout); scanf("%d%d%d%d",&n,&T,&m,&mod); inv[0
]=inv[1]=Fac[0]=Fac[1]=1; for(int i=2;i<=mod;i++){ Fac[i]=1ll*Fac[i-1]*i%mod; inv[i]=(-1ll*(mod/i)*inv[mod%i]%mod+mod)%mod; } for(int i=2;i<=mod;i++)inv[i]=1ll*inv[i-1]*inv[i]%mod; for(int i=1;i<=T;i++)scanf("%d",&a[i]); dfs(1,1,0); if(ans<0)ans+=mod; printf("%d\n",ans); return 0; }

bzoj 1272: [BeiJingWc2008]Gate Of Babylon