这是一道好题,值得品味
首先先不考虑有限制的情况是一道水题
但是一定要记得循环顺序,首先要循环第几种硬币,然后再循环多少钱
为什么呢?
如果先循环钱,就会导致重复 3 = 2 + 1 , 3 = 1 + 2
然后考虑有限制的情况
容斥一下:
答案 = 没有限制 - 第一种硬币突破限制 - 二 - 三 -四 + 一 & 二 ……
怎么求突破一种硬币限制呢?
只要这一种硬币使用 d[i]+1 个 剩下的 可以随便取(包括这一种硬币本身)
什么意思呢 首先先取这种硬币 d[i]+1 个 然后 继续递归,这种硬币还可以再取,这样就可以递归的考虑到所有的情况啦!
#include<bits/stdc++.h>
#define lca long long
using namespace std;
int c[5],d[5],T,s;
lca ans,f[100006];
void dfs(int x,int k,int sum)
{
if(sum<0) return ;
if(x==5)
{
if(k&1) ans-=f[sum];
else ans+=f[sum];
return ;
}
dfs(x+1,k,sum);
dfs(x+1,k+1,sum-(d[x]+1)*c[x]);
}
int main()
{
scanf("%d%d%d%d%d",&c[1],&c[2],&c[3],&c[4],&T);
f[0]=1;
for(int i=1;i<=4;i++)
for(int j=c[i];j<=100004;j++)
f[j]+=f[j-c[i]];
while(T--)
{
scanf("%d%d%d%d%d",&d[1],&d[2],&d[3],&d[4],&s);
ans=0;
dfs(1,0,s);
printf("%lld\n",ans);
}
}
心得:
1.我的dp非常的菜,非常的菜,非常的菜
2.容斥很麻烦,要好好看