题目:http://acm.hdu.edu.cn/showproblem.php?pid=1059
题意:1-6价值的硬币若干,问能不能平分。这道题一开始是思考的背包问题。因为这涉及到能不能刚好一半的容量。同理,既然是这样的,也可以用母函数。母函数就明显比背包会更简单。只要最后判断有没有系数就行了。
然后我有一句MMP一定要讲。我PE了1个小时。透李奶奶。因为我判断sum&1直接输出不行的时候少了个回车。我一直在后面的输出找格式错误。尴尬了。以后牢记教训。然后这个题的背包等我刷46DP的时候肯定会碰到再用DP做一遍。
#include<bits/stdc++.h>
#define INF 1e18
#define inf 1e9
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IOS ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;
const int _max = 20000*6+5;
// c1是保存各项质量砝码可以组合的数目
// c2是中间量,保存每一次的情况
int c1[_max], c2[_max];
int main(){
IOS;
int num[7],Cas = 0;
while(++Cas){
int maxn = 0;
for(int i = 1 ; i <= 6 ; i++) cin>>num[i];
if(!num[1]&&!num[2]&&!num[3]&&!num[4]&&!num[5]&&!num[6]) break;
for(int i = 1 ; i <= 6 ; i++) num[i] %= 60;
for(int i = 1 ; i <= 6 ; i++)
maxn += num[i]*i;
if(maxn&1){
cout<<"Collection #"<<Cas<<":"<<endl<<"Can't be divided."<<endl<<endl;
continue;
}
memset(c1,0,sizeof(c1));
memset(c2,0,sizeof(c2));
for(int i = 0 ; i <= num[1]*1 ; i++) c1[i] = 1;
int sum = num[1]*1;
for(int k = 2 ; k <= 6 ; k++){
for(int i = 0 ; i <= sum ; i++)
for(int j = 0 ; j <= num[k]*k ;j+=k){
c2[i+j] += c1[i];
}
sum += num[k]*k;
for(int i = 0 ; i <= sum ; i++){
c1[i] = c2[i];
c2[i] = 0;
}
}
/* for(int i = 1 ; i <= maxn ; i++)
cout<<c1[i]<<' ';
cout<<endl;*/
bool flag = true;
if(c1[(maxn>>1)] == 0) flag = false;
if(!flag) cout<<"Collection #"<<Cas<<":"<<endl<<"Can't be divided."<<endl;
else cout<<"Collection #"<<Cas<<":"<<endl<<"Can be divided."<<endl;
cout<<endl;
}
return 0;
}