1042: [HAOI2008]硬币购物
Submit: 3209 Solved: 2001
[Submit][Status][Discuss]
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
首先,计算出f[i]不限制硬币数量时,得到面值为i的方案数
\[f[i]=\sum _{k=1}^{4} f[i-c[k]],\left ( i-c[k]\geq 0 \right )\]
然后利用容斥原理:
ans=不限制硬币的方案数-一种硬币超过限制的方案数+两种硬币超过限制的方案数-三种硬币超过限制的方案数+四种硬币超过限制的方案数
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 5 #define LL long long 6 7 int T,s; 8 int c[5],d[5]; 9 LL ans,f[100005]; 10 11 void dfs(int x,int k,int sum) 12 { 13 if(sum<0) return; 14 if(x==5) 15 { 16 if(k&1) ans-=f[sum];//利用二进制的特性控制正负号 17 else ans+=f[sum]; 18 return; 19 } 20 dfs(x+1,k,sum); 21 dfs(x+1,k+1,sum-(d[x]+1)*c[x]); 22 } 23 24 int main() 25 { 26 for(int i=1;i<=4;i++) scanf("%d",&c[i]); 27 scanf("%d",&T); 28 f[0]=1; 29 for(int i=1;i<=4;i++) 30 for(int j=c[i];j<=100000;j++) 31 f[j]+=f[j-c[i]]; 32 while(T--) 33 { 34 for(int j=1;j<=4;j++) scanf("%d",&d[j]); 35 scanf("%d",&s); 36 ans=0; 37 dfs(1,0,s); 38 cout<<ans<<endl; 39 } 40 return 0; 41 }