1042: [HAOI2008]硬币购物
Description
硬币购物一共有4种硬币。面值分别为c1,c2,c3,c4。某人去商店买东西,去了tot次。每次带di枚ci硬币,买s
i的价值的东西。请问每次有多少种付款方法。
Input
第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000
Output
每次的方法数
Sample Input
1 2 5 10 2
3 2 3 1 10
1000 2 2 2 900
3 2 3 1 10
1000 2 2 2 900
Sample Output
4
27
27
我们可以先不要求硬币的个数,求一下背包。。。
然后我们用一下容斥原理。。。
对于s,我们如果不限制则是f[s]种方案。。
如果第一种硬币放多了也能达到s,则是f[s-(d1+1)*s1]
同理,可以求出第二种到第四种。。。
然后我们会发现我们减多了。。
所以要加上,第一种和第二种都放多了的情况。。。
同理。。。
然后我们又发现我们又加多了。。
所以要减去第一种,第二种,第三种都放多的情况。。
同理。。。
最后我们又发现我们减多了。。。
所以再加上四种硬币都放多的情况。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<queue> 10 #include<vector> 11 #include<set> 12 #define inf 1000000000 13 #define maxn 100000+5 14 #define maxm 10000+5 15 #define eps 1e-10 16 #define ll long long 17 #define for0(i,n) for(int i=0;i<=(n);i++) 18 #define for1(i,n) for(int i=1;i<=(n);i++) 19 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 20 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 22 using namespace std; 23 int read(){ 24 int x=0,f=1;char ch=getchar(); 25 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 26 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 27 return x*f; 28 } 29 int a[5],d[5]; 30 ll f[maxn],ans; 31 ll find(int a){ 32 if(a>=0)return f[a]; 33 else return 0; 34 } 35 int main(){ 36 //freopen("input.txt","r",stdin); 37 //freopen("output.txt","w",stdout); 38 for1(i,4)a[i]=read(); 39 int tot=read(); 40 f[0]=1; 41 for1(i,4) 42 for1(j,100000) 43 if(j-a[i]>=0) 44 f[j]+=f[j-a[i]]; 45 for1(i,tot){ 46 for1(j,4)d[j]=read(); 47 int s=read(); 48 ans=find(s); 49 for1(j,4) 50 ans-=find(s-(d[j]+1)*a[j]); 51 for1(j,4) 52 for(int k=j+1;k<=4;k++) 53 ans+=find(s-(d[j]+1)*a[j]-(d[k]+1)*a[k]); 54 for1(j,4) 55 for(int k=j+1;k<=4;k++) 56 for(int t=k+1;t<=4;t++) 57 ans-=find(s-(d[j]+1)*a[j]-(d[k]+1)*a[k]-(d[t]+1)*a[t]); 58 for1(j,4) 59 s-=(d[j]+1)*a[j]; 60 ans+=find(s); 61 printf("%lld\n",ans); 62 } 63 return 0; 64 }