題目概述
有
解題報告
顯然是二進制拆分做01揹包,然而數據範圍比較大,所以效率不是很好。
其實這道題可以用母函數輕鬆解決:(摘自維基和這裏)
在數學中,某個序列的母函數是一種形式冪級數,其每一項的係數可以提供關於這個序列的信息。
也就是說母函數是針對某個序列的,它的外在表現形式是一種形式冪級數。比如說有這樣一個序列
a0,a1,⋯,an ,構造一個函數f(x)=a0+a1x+a2x2+⋯+anxn 。則f(x) 是序列a0,a1,⋯,an 的母函數。比如說最常見的(1+x)n ,它是序列(n0),(n1),(n2)⋯(nn) 的母函數。
由此可見母函數各項係數就是各項的出現次數。對於一種面值爲
只需要多項式乘法求出母函數各項係數,然後找到第一個係數爲
示例程序
#include<cstdio>
using namespace std;
const int maxn=8000,val[3]={1,2,5};
int num[3],MAX,a[maxn+5],b[maxn+5];
int main(){
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
while (~scanf("%d%d%d",&num[0],&num[1],&num[2])){
if (!num[0]&&!num[1]&&!num[2]) break;
num[1]*=val[1];num[2]*=val[2];MAX=num[0]+num[1]+num[2];
for (int i=0;i<=MAX;i++) a[i]=i<=num[0],b[i]=0;
for (int t=1;t<3;t++){
for (int i=0;i<=MAX;i++)
for (int j=0;i+j<=MAX&&j<=num[t];j+=val[t])
b[i+j]+=a[i];
for (int i=0;i<=MAX;i++) a[i]=b[i],b[i]=0;
}
int ans=0;while (a[ans]&&ans<=MAX) ans++;printf("%d\n",ans);
}
return 0;
}