First, regardless of the limit, then there is dp[i] represents the number of solutions I yuan.
Then consider the limitations, and find that they can be dismissed.
In fact, the whole problem is two of the principle of repulsion. Feel the good.
#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>#defineMAXN 100500using namespacestd;Long Longf[maxn],c[5],d[5],n,s,ans;voidPRE_DP () {f[0]=1; for(Long LongI=1; i<=maxn- -; i++) { for(Long Longj=1; j<=4; j + +) if(I>=c[j]) f[i]+=f[i-C[j]]; for(Long Longj=1; j<=4; j + +) for(Long Longk=j+1; k<=4; k++) if(I>=c[j]+c[k]) f[i]-=f[i-c[j]-C[k]]; for(Long Longj=1; j<=4; j + +) for(Long Longk=j+1; k<=4; k++) for(Long Longl=k+1; l<=4; l++) if(I>=c[j]+c[k]+c[l]) f[i]+=f[i-c[j]-c[k]-C[l]]; if(i>=c[1]+c[2]+c[3]+c[4]) f[i]-=f[i-c[1]-c[2]-c[3]-c[4]]; }}voidWork () {ans=0; ans+=F[s]; for(Long LongI=1; i<=4; i++)if(S>=d[i]*c[i]) ans-=f[s-d[i]*C[i]]; for(Long LongI=1; i<=4; i++) for(Long Longj=i+1; j<=4; j + +) if(S>=d[i]*c[i]+d[j]*c[j]) ans+=f[s-d[i]*c[i]-d[j]*C[j]]; for(Long LongI=1; i<=4; i++) for(Long Longj=i+1; j<=4; j + +) for(Long Longk=j+1; k<=4; k++) if(S>=d[i]*c[i]+d[j]*c[j]+d[k]*c[k]) ans-=f[s-d[i]*c[i]-d[j]*c[j]-d[k]*C[k]]; if(s>=d[1]*c[1]+d[2]*c[2]+d[3]*c[3]+d[4]*c[4]) ans+=f[s-(d[1]*c[1]+d[2]*c[2]+d[3]*c[3]+d[4]*c[4])]; printf ("%lld\n", ans);}intMain () { for(Long LongI=1; i<=4; i++) scanf ("%lld",&C[i]); scanf ("%lld",&N); PRE_DP (); for(Long LongI=1; i<=n;i++) { for(Long Longj=1; j<=4; j + +) {scanf ("%lld", &d[j]);d [j]++;} scanf ("%lld",&s); Work (); } return 0;}
Bzoj 1042 Coin Shopping