母函数板子题
题意:
有三种硬币,分别是1,2,5。每次给分别你这三种硬币的数量,问你最少不能组合出来的钱数是多少。
输入三个0表示结束。输入的数量不会超过1000.
分析:
案例:1 1 3
用x的指数表示组合出来的硬币的价值,相应的系数表示相应的方案数
价值为1的硬币:要么有要么没有多项式为:1*x^0+1*x^1 = 1+x;
价值为2的硬币:要么有要么没有多项式为:1*x^0+1*x^2 = 1+x^2;
价值为5的硬币:多项式为:1*x^0+x^5+2*x^5+3*x^5 = 1+x^10+x^15;
多项式为:(1+x)*(1+x^2)*(1+x^10+x^15)
= (1+x^2+x+x^3)*(1+x^10+x^15)
= (1+x^10+x^15) + x^2*(1+x^10+x^15) +x*(1+x^10+x^15) +x^3*(1+x^10+x^15)
=(1+x^10+x^15) +(x^2+x^12+x^17) +(x+x^11+x^16) +(x^3+x^13+x^18)
=1+x+x^2+x^3+x^10+x^11+x^12+x^13+x^15+x^16+x^17+x^18
其中第一个未出现的系数是x^4 所以第一个不能组合出来的价值是4.
写程序实现上面的多项式相乘即可。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#define maxn 8005
using namespace std;
int main(){
int v[] = {1,2,5};
int n1[] = {0,0,0};
int n2[3];
int a[maxn],b[maxn];
while(cin>>n2[0]>>n2[1]>>n2[2] && (n2[0] != 0 || n2[1] != 0 || n2[2] != 0)){
int k = n2[0]+2*n2[1]+5*n2[2];
memset(a,0,sizeof(a));
a[0] = 1;
for(int i = 0;i<=2;i++){
memset(b,0,sizeof(b));
for(int j = n1[i];j<=n2[i]&&j*v[i]<=k;j++){
for(int t = 0; t+j*v[i]<=k;t++){
b[t+j*v[i]] += a[t];
}
}
memcpy(a,b,sizeof(b));
}
bool f = true;
for(int i = 1;i < k;i++){
if(a[i]==0){
cout<<i<<endl;
f = false;
break;
}
}
if(f){
cout<<k+1<<endl;
}
}
return 0;
}