bzoj 1042
完全背包预处理再容斥。
符合条件的付款方法数=所有付款方法数-不符合的方法数。
所有付款方法数可以用完全背包求出。
根据容斥原理,不符合的方法数等于第一种硬币不符合的方案数+第二种硬币不符合的方案数+……-第一种和第二种硬币都不符合的方案数-第一种和第三种硬币都不符合的方案数-……+第一种和第二种和第三种硬币都不符合的方案数+第一种和第二种和第四种硬币都不符合的方案数+……-四种硬币都不符合的方案数。
推荐用DFS来实现,比较好写。时间复杂度大概是O(S+T)。
#include<cstdio> #include<cctype> #include<cstring> #include<algorithm> using namespace std; const int maxs=100001; long long read(){ char c; while(!isdigit(c=getchar())); long long x=c-'0'; while(isdigit(c=getchar())) x=x*10+c-'0'; return x; } long long ans,c[4],d[4],s,f[maxs]; void dfs(int o,int s,int num){ if(s<0) return; if(o==4){ if(num&1) ans-=f[s]; else ans+=f[s]; return; } dfs(o+1,s,num); dfs(o+1,s-(d[o]+1)*c[o],num+1); } int main(){ f[0]=1; for(int i=0;i<4;i+=1) c[i]=read(); for(int i=0;i<4;i+=1) for(int j=c[i];j<maxs;j+=1) f[j]+=f[j-c[i]]; int t=read(); while(t--){ ans=0; for(int i=0;i<4;i+=1) d[i]=read(); dfs(0,s=read(),0); printf("%lld\n",ans); } return 0; }