第一反应 多重背包 wodema 我准备好我的单调队列优化了 emmmm1k次???怎么搞????
瓜想20min 难道我真的无法自主做出一道题吗???是的呢
先考虑完全背包 然后根据dalao们说的 就像区间相减一样 emmm所以用f[money]-f[money-c[i]*(d[i]+1)]
这个原理有点点像前天做的消失之物 但是这个要用到容斥 容斥我又双叒叕没有系统搞过
欧阳说下面这个搜索版的要好理解一点 这个思想真的好巧妙!!!!
容斥大概是 求A,B,C,D....集合的面积 即A+B+C+...-A∩B-A∩C-B∩C-...+A∩B∩C+B∩C∩D... 大概这样推下去
最后注意开long long
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define ll long long #define rg register const int N=200+5,M=100000+5,inf=0x3f3f3f3f,P=99999997; ll ans,T,m,a[5],d[5],f[M]; template <class t>void rd(t &x){ x=0;int w=0;char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=w?-x:x; } void dfs(int nw,int mon,int fla){ if(mon<0) return; if(nw>4) {ans+=f[mon]*fla;return;} dfs(nw+1,mon,fla); dfs(nw+1,mon-a[nw]*(d[nw]+1),-fla); } int main(){ // freopen("in.txt","r",stdin); f[0]=1; for(int i=1;i<=4;++i){ rd(a[i]); for(int v=a[i];v<M;++v) f[v]+=f[v-a[i]]; } rd(T); while(T--){ for(int i=1;i<=4;++i) rd(d[i]); rd(m); ans=0; dfs(1,m,1); printf("%lld ",ans); } return 0; }