洛谷 P2563 [AHOI2001]质数和分解
Description
任何大于 1 的自然数 n 都可以写成若干个大于等于 2 且小于等于 n 的质数之和表达式(包括只有一个数构成的和表达式的情况),并且可能有不止一种质数和的形式。例如,9 的质数和表达式就有四种本质不同的形式:
9 = 2 + 5 + 2 = 2 + 3 + 2 + 2 = 3 + 3 + 3 = 2 + 7 。
这里所谓两个本质相同的表达式是指可以通过交换其中一个表达式中参加和运算的各个数的位置而直接得到另一个表达式。
试编程求解自然数 n 可以写成多少种本质不同的质数和表达式。
Input
- 文件中的每一行存放一个自然数 n(2 < n < 200) 。
Output
- 依次输出每一个自然数 n 的本质不同的质数和表达式的数目。
Sample Input
2 200
Sample output
1 9845164
题解
- 原谅我第一时间没想到正解qwq。我第一反应是搜索,但你细想发现搜索好像写不出来,毫无思路(可能是我菜吧)。所以转换思路我发现,这题可以这样抽象:
- 有一个空间为N的包,还有很多个物品,每个物品的所占空间都是质数(200以内),每个物品可以用无限次,请问能装出N的包吗?方案数为多少?
- 又物品可用欧拉筛出来,所以能否装出N的包就是一个裸奔完全背包。它问方案数稍微改一下就好(把可行改成方案数)
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 205
using namespace std;
int T, n;
int pri[maxn], w[maxn], dp[maxn];
bool flag[maxn] = {1, 1};
int main()
{
for(int i = 2; i <= 200; i++)
{
if(!flag[i]) pri[++n] = i;
for(int j = 1; j <= n && pri[j] * i <= 200; j++)
{
flag[pri[j] * i] = 1;
if(i % pri[j] == 0) break;
}
}
for(int i = 1; i <= n; i++) w[i] = pri[i];
while(scanf("%d", &T) != EOF)
{
memset(dp, 0, sizeof(dp));
dp[0] = 1;
for(int i = 1; i <= n; i++)
for(int j = w[i]; j <= T; j++)
dp[j] += dp[j - w[i]];
cout << dp[T] << endl;
}
return 0;
}