START:

2021-08-09

15:28:07

题目链接:

https://www.luogu.com.cn/problem/P1832

 

给定一个正整数n,求将其分解成若干个素数之和的方案总数。

 

输入格式

 

一行:一个正整数n

 

输出格式

 

一行:一个整数表示方案总数

 

输入输出样例

 

输入 #1复制
7
输出 #1复制
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