1042: [HAOI2008]硬币购物

Time Limit: 10 Sec  Memory Limit: 162 MB
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

Sample Output

4
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 }

 

posted @ 2018-07-17 20:32  InWILL  阅读(307)  评论(0编辑  收藏  举报