BZOJ 1042: [HAOI2008]硬币购物(容斥原理)
http://www.lydsy.com/JudgeOnline/problem.php?id=1042
题意:
思路:
如果不考虑硬币个数的话,这就是一道完全背包的题目。
直接求的话行不通,于是这里要用容斥原理来做。
简单来说,ans=一种没超-一种硬币超+两种硬币超-三种硬币超+四种硬币超。
1 /************************************************************** 2 Problem: 1042 3 User: Vortex 4 Language: C++ 5 Result: Accepted 6 Time:60 ms 7 Memory:2068 kb 8 ****************************************************************/ 9 10 #include<iostream> 11 #include<algorithm> 12 #include<cstring> 13 #include<cstdio> 14 #include<sstream> 15 #include<vector> 16 #include<stack> 17 #include<queue> 18 #include<cmath> 19 #include<map> 20 #include<set> 21 using namespace std; 22 typedef long long ll; 23 typedef pair<int,int> pll; 24 const int INF = 0x3f3f3f3f; 25 const int maxn = 100000 + 5; 26 27 int s; 28 ll ans; 29 int c[5],d[5]; 30 ll f[maxn]; 31 32 void init() 33 { 34 memset(f,0,sizeof(f)); 35 f[0]=1; 36 for(int i=1;i<=4;i++) 37 { 38 for(int j=c[i];j<=100000;j++) 39 f[j]+=f[j-c[i]]; 40 } 41 } 42 43 void dfs(int cur, int cnt, int sum) 44 { 45 if(sum<0) return; 46 if(cur==5) 47 { 48 if(cnt&1) ans-=f[sum]; 49 else ans+=f[sum]; 50 return; 51 } 52 dfs(cur+1,cnt+1,sum-(d[cur]+1)*c[cur]); 53 dfs(cur+1,cnt,sum); 54 } 55 56 int main() 57 { 58 //freopen("in.txt","r",stdin); 59 int T; 60 for(int i=1;i<=4;i++) scanf("%d",&c[i]); 61 scanf("%d",&T); 62 init(); 63 while(T--) 64 { 65 for(int i=1;i<=4;i++) scanf("%d",&d[i]); 66 scanf("%d",&s); 67 ans=0; 68 dfs(1,0,s); 69 printf("%lld\n",ans); 70 } 71 return 0; 72 } 73