START:
2021-08-09
15:28:07
题目链接:
https://www.luogu.com.cn/problem/P1832
给定一个正整数n,求将其分解成若干个素数之和的方案总数。
输入格式
一行:一个正整数n
输出格式
一行:一个整数表示方案总数
输入输出样例
7
3
说明/提示
【样例解释】
7=7 7=2+5
7=2+2+3
【福利数据】
【输入】 20
【输出】 26
【数据范围及约定】
对于30%的数据 1<=n<=10
对于100%的数据,1<=n<=10^3
该题 zha 一看是数学题,但是这里可以使用DP。
我们可以将输入的n视为背包的容量,从1到n的质数的个数看做物品的种类,每个质数看做物品且每个物品可以拿无数次,这就是完全背包问题。 我们定义cnt来计算质数的个数,用sushu[N]数组来储存每一个质数(下标从0开始),写一个判断质数的函数以及初始函数init(),定义dp[N]数组,dp[i]:表示将i分解成质数相加的所有的方案数。那么我们可以知道,对于每一个dp[i],我们有:dp[i]=dp[i]+dp[i-质数],并初始化dp[0]=1。这就是核心函数solve()所包含的内容了,下面给出除了solve()函数外所有代码:
#include<iostream>
using namespace std;
typedef long long LL;
const int N=1005;
int n,cnt=0;
LL sushu[200];
LL dp[N];
bool isprime(int u){
for(int i=2;i<=u/i;i++){
if(u%i==0)return false;
}
return true;
}
void init(){
for(int i=2;i<=n;i++){
if(isprime(i))sushu[cnt++]=i;
}
}
void solve(){
}
int main()
{
cin>>n;
init();
solve();
return 0;
}
现在开始写solve函数:按照完全背包的模板来:
最外层for循环是遍历每一个质数,内层循环是遍历从当前质数sushu[i]到n的所有dp[ ]数组,然后每个dp[i]=dp[i]+dp[i-质数],所以
dp[j]+=dp[j-sushu[i]];
void solve(){
dp[0]=1;
for(int i=0;i<cnt;i++){
for(int j=sushu[i];j<=n;j++){
dp[j]+=dp[j-sushu[i]];
}
}
cout<<dp[n]<<endl;
}
最后奉上最终代码:
#include<iostream>
using namespace std;
typedef long long LL;
const int N=1005;
int n,cnt=0;
LL sushu[200];
LL dp[N];
bool isprime(int u){
for(int i=2;i<=u/i;i++){
if(u%i==0)return false;
}
return true;
}
void init(){
for(int i=2;i<=n;i++){
if(isprime(i))sushu[cnt++]=i;
}
}
void solve(){
dp[0]=1;
for(int i=0;i<cnt;i++){
for(int j=sushu[i];j<=n;j++){
dp[j]+=dp[j-sushu[i]];
}
}
cout<<dp[n]<<endl;
}
int main()
{
cin>>n;
init();
solve();
return 0;
}
END:
2021-08-09
15:44:05
















