【问题描述】
2019可以被分解成若干个两两不同的素数,请问不同的分解方案有多少种?
注意:分解方案不考虑顺序,如 2 + 2017 = 2019 和 2017 + 2 = 2019 属于同一种方案。
答案:55965365465060
题解
01背包:
f[i][j]:从前 i 个物品中选,且总体积恰好为 j 的方案的数量
#include <iostream>
using namespace std;
const int N = 2500;
int k = 1;
int st[N], prime[N];
long long f[N][N];
void init() // 埃氏筛法
{
for (int i = 2; i <= 2019; i ++)
{
if(!st[i])
{
prime[k ++] = i;
for (int j = i + i; j <= 2019; j += i) st[j] = true;
}
}
}
int main()
{
init(); // 初始化,获取素数表
f[0][0] = 1; // 容量为0也是一种方案
for (int i = 1; i < k; i ++)
for (int j = 0; j <= 2019; j ++)
{
f[i][j] = f[i - 1][j];
if(j >= prime[i]) f[i][j] += f[i - 1][j - prime[i]];
}
cout << f[k - 1][2019] << endl;
return 0;
}
空间优化:
#include <iostream>
using namespace std;
const int N = 2500;
int k = 1;
int st[N], prime[N];
long long f[N];
void init()
{
for (int i = 2; i <= 2019; i ++)
{
if(!st[i])
{
prime[k ++] = i;
for (int j = i + i; j <= 2019; j += i) st[j] = true;
}
}
}
int main()
{
init();
f[0] = 1;
for (int i = 1; i < k; i ++)
for (int j = 2019; j >= prime[i]; j --)
{
f[j] += f[j - prime[i]];
}
cout << f[2019] << endl;
return 0;
}