定义了一种数super prime,数的本身是一个素数,且在素数表里的下标(从1开始)也是一个素数。然后给定一个n,求用最少的superprime相加得到n的方法。
解法,因为数据很小,Number is not more than 10000. 在10000内的super prime也很少,只有201个,所以可以直接本地打表得出。随后就是一个很简单的背包。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int sprime[201]={3,5,11,17,31,41,59,67,83,109,127,157,179,191,211,241,277,283,331,353,367,401,431,461,509,547,563,587,599,617,709,739,773,797,859,877,919,967,991,1031,1063,1087,1153,1171,1201,1217,1297,1409,1433,1447,1471,1499,1523,1597,1621,1669,1723,1741,1787,1823,1847,1913,2027,2063,2081,2099,2221,2269,2341,2351,2381,2417,2477,2549,2609,2647,2683,2719,2749,2803,2897,2909,3001,3019,3067,3109,3169,3229,3259,3299,3319,3407,3469,3517,3559,3593,3637,3733,3761,3911,3943,4027,4091,4133,4153,4217,4273,4339,4397,4421,4463,4517,4549,4567,4663,4759,4787,4801,4877,4933,4943,5021,5059,5107,5189,5281,5381,5441,5503,5557,5623,5651,5701,5749,5801,5851,5869,6037,6113,6217,6229,6311,6323,6353,6361,6469,6599,6653,6661,6691,6823,6841,6863,6899,7057,7109,7193,7283,7351,7417,7481,7523,7607,7649,7699,7753,7841,7883,8011,8059,8101,8117,8221,8233,8287,8377,8389,8513,8527,8581,8719,8747,8761,8807,8849,8923,8999,9041,9103,9293,9319,9403,9461,9539,9619,9661,9739,9833,9859,9923,9973
};
int f[10001],cnt[10001],line[10001];
bool cmp(int a,int b)
{
return a>b?a:b;
}
int main()
{
int i,j,n,ans,ll;
memset(f,-1,sizeof(f));
memset(cnt,0,sizeof(cnt));
for (i=3; i<10001; i++)
{
for (j=0; j<201; j++)
{
if (i == sprime[j])
{
f[i]=-sprime[j];
cnt[i]=1;
break;
}
else if (sprime[j] > i)
{
break;
}
else if (i > sprime[j])
{
if (f[i-sprime[j]] != -1 && (cnt[i] == 0 || cnt[i] > cnt[i-sprime[j]]+1))
{
f[i]=sprime[j];
cnt[i]=cnt[i-sprime[j]]+1;
}
}
}
}
scanf("%d",&n);
if (f[n] == -1)
{
printf("0\n");
return 0;
}
ll=0;
printf("%d\n",cnt[n]);
while (f[n] > 0)
{
line[ll]=f[n];
ll++;
n-=f[n];
}
line[ll]=-f[n];
ll++;
sort(line,line+ll,cmp);
for (i=0; i<ll-1; i++)
{
printf("%d ",line[i]);
}
printf("%d\n",line[i]);
}