这道题是整数拆分的变形。
由于钱币最多只有25种,所以这道题也可以用记忆式搜索、DP来做。
下面贴的是母函数法的代码。
k的初值:如果填l加一个判断条件(t1=k+j*coin[i]<=n),则1.15s超时,
如果在初值上填写n-j*coin[i],则0.319s不超时(第十二个点)。
/*
ID:szwjcch971
LANG:C++
TASK:money
*/
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
/*void swapshuzu(long long a[10035],long long b[10035]){
long long t;
b=a;
}*/
int min(int a,int b){
return a<b?a:b;
}
int main(){
int coin[26];
int v,n,temp,i,j,k,l;
long long t1,t2;
long long cishu[10035],tem[10035];
FILE *fin=fopen("money.in","r");
FILE *fout=fopen("money.out","w");
fscanf(fin,"%d",&v);
fscanf(fin,"%d",&n);
//printf("%d %d\n",v,n);
for(i=1;i<=v;i++)fscanf(fin,"%d",&coin[i]);
for(i=1;i<v;i++){
for(j=i+1;j<=v;j++){
if(coin[i]>coin[j]){
temp=coin[i];coin[i]=coin[j];coin[j]=temp;
}
}
}
memset(cishu,0,sizeof(cishu));
memset(tem,0,sizeof(tem));
cishu[0]=1;
for(i=1;i<=v;i++){
l=n;
while(!cishu[l])l--;
for(j=0;j<=l;j++)tem[j]=cishu[j];
for(j=1;j<=n/coin[i];j++){
for(k=min(l,n-j*coin[i]);k>=0;k--){
//printf("I=%lld,J=%lld,K=%lld,T1=%lld,\n",i,j,k,t1);
cishu[k+j*coin[i]]+=tem[k];
}
}
}
fprintf(fout,"%lld\n",cishu[n]);
return 0;
}
附第12组数据:
Input:
8 10000
1 2 3 4 5 6 20 25
Output:
17166982