背包DP 方案数---P1832 A+B Problem(再升级)

P1832 A+B Problem(再升级)

题面描述

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

题解

我们可以考虑背包DP实现

背包DP方案数板子题

f[ i ] = f[ i ] + f[ i - a[j] ] 

f[ j ] 表示数字 j 用若干个素数表示的方案总数

注意

1.线性筛不要写错:

  1)not_prime[maxn] maxn>=n

  2)memset not_prime 数组之后,0,1初始化不是素数

 2.方案数 DP 数组要开 long long

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<queue>

using namespace std;

typedef long long ll;

inline int read()
{
    int ans=0;
    char last=' ',ch=getchar();
    while(ch<'0'||ch>'9') last=ch,ch=getchar();
    while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
    if(last=='-') ans=-ans;
    return ans;
}

int n;
int prime[1000],not_prime[1050],cnt=0;
ll f[5000];

void xxs()
{
    memset(prime,0,sizeof(prime));
    memset(not_prime,0,sizeof(not_prime));
    not_prime[0]=not_prime[1]=1;
    for(int i=2;i<=n;i++){
        if(!not_prime[i]) prime[++cnt]=i;
        for(int j=1;j<=cnt;j++){
            if(i*prime[j]>n) break;
            not_prime[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}

int main()
{
    n=read();
    xxs();
    f[0]=1;
    for(int i=1;i<=cnt;i++)
      for(int j=prime[i];j<=n;j++)
         f[j]+=f[j-prime[i]];
    printf("%lld\n",f[n]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xiaoyezi-wink/p/11972112.html