[HAOI2008]硬币购物

题目描述

硬币购物一共有4种硬币。面值分别为c1,c2,c3,c4。某人去商店买东西,去了tot次。每次带di枚ci硬币,买si的价值的东西。请问每次有多少种付款方法。

输入输出格式

输入格式:

第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s

输出格式: 

每次的方法数

输入输出样例

输入样例#1:
1 2 5 10 2
3 2 3 1 10
1000 2 2 2 900
输出样例#1:
4
27

说明

di,s<=100000

tot<=1000

题解:

一开始认为要求出一个4元方程的解的个数,用容斥求出所有GCD(a,b,c,d)|si的解

但时间复杂度太高,且条件限制不好做。

后面看到一种解法:

用dp求f[i]为钱数为i时的方案总数

显然f[i]=signma(f[i-c[j]])

复杂度为O(4*s)

再用容斥原理求出所有方案,减去1超出限制,再减去2超限,还有3和4。再加上1,2超限.....

i超出限制的方案为f[si-(d[j]+1)*c[j]]

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 long long c[5],d[5],tot;
 7 long long f[1000005],ans;
 8 int main()
 9 {long long i,j,s;
10     cin>>c[1]>>c[2]>>c[3]>>c[4]>>tot;
11     f[0]=1;
12     for (i=1;i<=4;i++)
13     for (j=c[i];j<=100000;j++)
14     {
15         f[j]+=f[j-c[i]];
16     }
17     for (i=1;i<=tot;i++)
18     {
19         for (j=1;j<=4;j++)
20         scanf("%I64d",&d[j]);
21         scanf("%I64d",&s);
22         ans=f[s];
23         if ((d[1]+1)*c[1]<=s)
24         ans-=f[s-(d[1]+1)*c[1]];
25         if ((d[2]+1)*c[2]<=s)
26         ans-=f[s-(d[2]+1)*c[2]];
27         if ((d[3]+1)*c[3]<=s)
28         ans-=f[s-(d[3]+1)*c[3]];
29         if ((d[4]+1)*c[4]<=s)
30         ans-=f[s-(d[4]+1)*c[4]];
31         
32         if ((d[1]+1)*c[1]+(d[2]+1)*c[2]<=s)
33         ans+=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]];
34         if ((d[1]+1)*c[1]+(d[3]+1)*c[3]<=s)
35         ans+=f[s-(d[1]+1)*c[1]-(d[3]+1)*c[3]];
36         if ((d[1]+1)*c[1]+(d[4]+1)*c[4]<=s)
37         ans+=f[s-(d[1]+1)*c[1]-(d[4]+1)*c[4]];
38         if ((d[3]+1)*c[3]+(d[2]+1)*c[2]<=s)
39         ans+=f[s-(d[3]+1)*c[3]-(d[2]+1)*c[2]];
40         if ((d[4]+1)*c[4]+(d[2]+1)*c[2]<=s)
41         ans+=f[s-(d[4]+1)*c[4]-(d[2]+1)*c[2]];
42         if ((d[3]+1)*c[3]+(d[4]+1)*c[4]<=s)
43         ans+=f[s-(d[3]+1)*c[3]-(d[4]+1)*c[4]];
44         
45         if ((d[1]+1)*c[1]+(d[2]+1)*c[2]+(d[3]+1)*c[3]<=s)
46         ans-=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3]];
47         if ((d[4]+1)*c[4]+(d[2]+1)*c[2]+(d[3]+1)*c[3]<=s)
48         ans-=f[s-(d[4]+1)*c[4]-(d[2]+1)*c[2]-(d[3]+1)*c[3]];
49         if ((d[1]+1)*c[1]+(d[4]+1)*c[4]+(d[3]+1)*c[3]<=s)
50         ans-=f[s-(d[1]+1)*c[1]-(d[4]+1)*c[4]-(d[3]+1)*c[3]];
51         if ((d[1]+1)*c[1]+(d[4]+1)*c[4]+(d[2]+1)*c[2]<=s)
52         ans-=f[s-(d[1]+1)*c[1]-(d[4]+1)*c[4]-(d[2]+1)*c[2]];
53         
54         if ((d[1]+1)*c[1]+(d[2]+1)*c[2]+(d[3]+1)*c[3]+(d[4]+1)*d[4]<=s)
55         ans+=f[s-(d[1]+1)*c[1]-(d[2]+1)*c[2]-(d[3]+1)*c[3]-(d[4]+1)*d[4]];
56         cout<<ans<<endl;
57     }
58 }

 

posted @ 2017-07-27 20:24  Z-Y-Y-S  阅读(220)  评论(0编辑  收藏  举报