题解:学而思编程 质数和分解
【题目来源】
学而思编程:质数和分解
【题目描述】
任何大于 \(1\) 的自然数 \(n\) 都可以写成若干个大于等于 \(2\) 且小于等于 \(n\) 的质数之和表达式(包括只有一个数构成的和表达式的情况),并且可能有不止一种质数和的形式。例如,\(9\) 的质数和表达式就有四种本质不同的形式:
\(9=2+5+2=2+3+2+2=3+3+3=2+7\)。
这里所谓两个本质相同的表达式是指可以通过交换其中一个表达式中参加和运算的各个数的位置而直接得到另一个表达式。
试编程求解自然数 nn 可以写成多少种本质不同的质数和表达式。
【输入】
一个自然数 \(n(2≤n≤1000)\) 。
【输出】
输出 \(n\) 的本质不同的质数和表达式的数目。
【输入样例】
200
【输出样例】
9845164
【代码详解】
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int N = 1005;
int n, w[N], cur, dp[N]; // n: 目标数,w: 存储质数,cur: 质数个数,dp: 动态规划数组
// 判断一个数是否为质数
bool isprime(int x)
{
if (x < 2) // 小于2的数不是质数
{
return 0;
}
for (int i = 2; i * i <= x; i++) // 只需检查到sqrt(x)
{
if (x % i == 0) // 如果能被整除,则不是质数
{
return 0;
}
}
return 1; // 是质数
}
signed main()
{
cin >> n; // 读入目标数
// 收集所有小于等于n的质数
for (int i = 2; i <= n; i++)
{
if (isprime(i))
{
w[++cur] = i; // 将质数存入数组
}
}
dp[0] = 1; // 凑出0的方法数为1(不选任何质数)
// 完全背包问题:计算用质数凑出每个数的方法数
for (int i = 1; i <= cur; i++) // 遍历每个质数
{
for (int j = w[i]; j <= n; j++) // 从质数本身开始遍历
{
dp[j] += dp[j - w[i]]; // 状态转移方程
}
}
cout << dp[n]; // 输出凑出n的方法数
return 0;
}
【运行结果】
200
9845164
浙公网安备 33010602011771号