题意:给定n和k,要求找出k个互不相同的素数,使其和==n,求这样的组合有多少中
思路:因为素数互不相同,自然想到了0-1背包,可是怎么背包却想了很久,因为多了一个限制:k,那么必须用两维数组来做,用dp[M][K]表示在组成M时,K个素数互不相同的情况,于是可以用0-1背包来对每个prime进行dp:
dp[m][k] = dp[m][k] + dp[m-prime[i]][k-1]; //注意数组不要越界
写完后发现代码运行需要500ms,别人的都是1xms,怎么差别这么大?看了别人的思路和自己的差不多,可是问什么时间差这么多呢?希望路过的神牛指点一二。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#include <set>
#include <bitset>
#include <vector>
using namespace std;
const int BORDER = (1<<20)-1;
const int MAXSIZE = 37;
const int MAXN = 1250;
const int INF = 0x7ffffff;
#define CLR(x,y) memset(x,y,sizeof(x))
int n,ans,k,index;
int prime[MAXN],arr_dp[MAXN][MAXN];
int init()
{
CLR(arr_dp,0);
arr_dp[0][0] = 1;
return 0;
}
bool _prime(const int& num)
{
int tmp = (int)sqrt(float(num))+1;
for(int i = 2; i < tmp; ++i)
if(!(num%i))
return false;
return true;
}
int find_prime()
{
int i,j;
index = 0;
for(i = 2; i <= 1120; ++i)
if(_prime(i))
prime[index++] = i;
return 0;
}
int dp()
{
int bor = index;
for(int i = 0; i < index; ++i)
if(prime[i] > n)
{
bor = i;
break;
}
for( int i = 0; i < bor; ++i)
for(int j = n; j >= prime[i]; --j)
for(int h = k; h >= 1; --h)
arr_dp[j][h] += arr_dp[j-prime[i]][h-1];
OUT(arr_dp[n][k]);
return 0;
}
int main()
{
int i,j,tmp;
find_prime();
while(scanf("%d%d",&n,&k))
{
if(!n && !k)
break;
init();
dp();
}
return 0;
}