2019可以被分解成若干个两两不同的素数,请问不同的分解方案有多少种?
注意:分解方案不考虑顺序,如2+2017=2019和2017+2=2019属于同一种方案。
#include<bits/stdc++.h>
using namespace std;
#define MAXN 200000
typedef unsigned long long ull;
vector<ull>p;
ull dp[MAXN];
int is_prime(int n){
for(int i=2;i*i<=n;i++)
if(n%i==0)return 0;
return n>1;
}
void prime(){//将2-2019的质数加入质数表
p.push_back(0);
for(int i=2;i<=2019;i++)
if(is_prime(i))p.push_back(i);
}
int main()
{
prime();
dp[0]=1;
for (int i = 1; i <p.size(); i++)
for (int j = 2019; j >=p[i]; j--)
dp[j] += dp[j - p[i]];
cout<<dp[2019]<<endl;
return 0;
}
当然,也可以记忆化搜索
#include<bits/stdc++.h>
using namespace std;
#define MAXN 200000
typedef unsigned long long ull;
vector<ull>p;//质数表
ull f[3000][3000];//缓存表,用于记忆化 f[i][j] 表示:前i个数中和为j的情况数为:f[i][j]
int flag[2]={0,1};
int is_prime(int n){
for(int i=2;i*i<=n;i++)
if(n%i==0)return 0;
return n>1;
}
void prime(){//将2-2019的质数加入质数表
for(int i=2;i<=2019;i++)
if(is_prime(i))p.push_back(i);
}
//就是从质数表中选数使得和为2019
ull dfs(int step,int sum) {
if(f[step][sum]!=-1) return f[step][sum];//如果表中情况已被搜索过
if(sum == 2019) return 1;//到结果
if(step>= p.size()||sum> 2019) return 0;//越界
ull t = 0;
for(int i=0;i<2;i++)//t为情况总和
t+=dfs(step+1,sum+flag[i]*p[step]);//是否选择当前这个素数
return f[step][sum] = t;
}
int main()
{
prime();
memset(f,-1,sizeof(f));
return cout<<dfs(0,0)<<endl,0;
}