题目:
题目描述
任何大于 111 的自然数 nnn 都可以写成若干个大于等于 222 且小于等于 nnn 的质数之和表达式(包括只有一个数构成的和表达式的情况),并且可能有不止一种质数和的形式。例如,999 的质数和表达式就有四种本质不同的形式:9 = 2 + 5 + 2 = 2 + 3 + 2 + 2 = 3 + 3 + 3 = 2 + 7 。
这里所谓两个本质相同的表达式是指可以通过交换其中一个表达式中参加和运算的各个数的位置而直接得到另一个表达式。
试编程求解自然数 nnn 可以写成多少种本质不同的质数和表达式。
输入格式
文件中的每一行存放一个自然数 n(2≤n≤200) 。
输出格式
依次输出每一个自然数 nnn 的本质不同的质数和表达式的数目。
样例
输入 #1
2
200
输出 #1
1
9845164
解析:
这道题首先用筛法求出一个素数表,由于数据范围是200以内,所以处理到二百稍多一点就够了,然后利用完全背包求解即可
关于不重复的式子:
我们处理的素数是从小到大处理的,我们写背包的时候也是正序循环过去的,所以当我们选完了一个物品我们就不可能再回来选这个物品,因此7 + 2是不会存在的。
代码:
#include<bits/stdc++.h>
using namespace std;
long long v[210],prime[100],num=0,n,dp[300];
void truncsqrt() {
for(int i = 2; i <= 200; i++) {
if(!v[i]) {
v[i] = i;
prime[++num] = i;
}
for(int j = 1; j <= num; j++) {
if(prime[j] > 200 / i || prime[j] > v[i])
break;
v[i*prime[j]] = prime[j];
}
}
}
int main() {
truncsqrt();
while(scanf("%d" ,&n) != EOF) { //由题目中“每一行存放一个自然数 n”可以推断出这是多组数据。。。。不要笑,不按多组数据写会卡掉一个点的。。。。。
memset(dp,0,sizeof(dp));
dp[0] = 1;
for(int i = 1; i <= num; i++) {
for(int j = prime[i]; j <= n; j++) {
dp[j] += dp[j - prime[i]];
}
}
printf("%d\n",dp[n]);
}
return 0;
}