硬币购物一共有4种硬币。面值分别为c1,c2,c3,c4。某人去商店买东西,去了tot次。每次带di枚ci硬币,买s
i的价值的东西。请问每次有多少种付款方法。
硬币购物一共有4种硬币。面值分别为c1,c2,c3,c4。某人去商店买东西,去了tot次。每次带di枚ci硬币,买s
i的价值的东西。请问每次有多少种付款方法。
第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000
每次的方法数
HOME Back
如果不考虑硬币个数,那么这题是一个简单的完全背包。
先用100W的复杂度预处理出dp dp[i]表示达到i的方案数
然后考虑 对于第i硬币数目大于d[i]的方案数的不行的
对于这种情况 ans应该减去dp[s-(d[i]+1)*c[i]]
然后考虑去重 即用容斥 奇加偶减
即可得到答案
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; const int N=10005; long long dp[1000005],ans; int c[5],tot,d[5],s; void dfs(int st,int hav,int sum) { if(st>4) { if(sum>s||hav==0) return ; if(hav&1) ans-=dp[s-sum]; else ans+=dp[s-sum]; return ; } dfs(st+1,hav+1,sum+c[st]*(d[st]+1)); dfs(st+1,hav,sum); } int main() { int i,j,q; while(~scanf("%d%d%d%d%d",&c[1],&c[2],&c[3],&c[4],&tot)) { memset(dp,0,sizeof(dp)); dp[0]=1; for(i=1;i<=4;i++) for(j=c[i];j<=1000000;j++) dp[j]+=dp[j-c[i]]; while(tot--) { for(i=1;i<=4;i++) scanf("%d",&d[i]); scanf("%d",&s); ans=dp[s]; dfs(1,0,0); cout<<ans<<endl; } } return 0; }