洛谷 P2563 [AHOI2001]质数和分解 题解
P2563 [AHOI2001]质数和分解
题目描述
任何大于 1 的自然数 n 都可以写成若干个大于等于 2 且小于等于 n 的质数之和表达式(包括只有一个数构成的和表达式的情况),并且可能有不止一种质数和的形式。例如,9 的质数和表达式就有四种本质不同的形式:
9 = 2 + 5 + 2 = 2 + 3 + 2 + 2 = 3 + 3 + 3 = 2 + 7 。
这里所谓两个本质相同的表达式是指可以通过交换其中一个表达式中参加和运算的各个数的位置而直接得到另一个表达式。
试编程求解自然数 n 可以写成多少种本质不同的质数和表达式。
输入格式
文件中的每一行存放一个自然数 n(2 < n < 200) 。
输出格式
依次输出每一个自然数 n 的本质不同的质数和表达式的数目。
输入输出样例
输入 #1
2
200
输出 #1
1
9845164
【思路】
筛法 + 完全背包
【题目大意】
每一个数可以被拆分成多少种质数相加的形势
【题目分析】
首先这是被拆分成许多个数
这些数都是质数
假设是已知的
那就可以用完全背包来拼凑某个数了
然后要怎么知道质数呢?
很简单的筛法
【核心思路】
先预处理出200以内的质数
然后跑完全背包
将200以内的每个数的组合方式预处理出来
最后输出就好了
【完整代码】
#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int Max = 205;
int prime[Max];
bool use[Max];
int bb[Max];
int sum = 0;
signed main()
{
for(register int i = 2;i <= 200;++ i)
{
if(use[i] == false)
{
prime[++ sum] = i;
for(register int j = i * 2;j <= 200;j += i)
use[j] = true;
}
}
bb[0] = 1;
for(register int i = 1;i <= sum;++ i)
for(register int j = prime[i];j <= 200;++ j)
bb[j] += bb[j - prime[i]];
int n;
while(scanf("%lld",&n) != EOF)
{
cout << bb[n] << endl;
}
return 0;
}