蓝桥杯2019国赛题:质数拆分(简单思维+背包)

题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

将 2019 拆分为若干个两两不同的质数之和,一共有多少种不同的方法?

注意交换顺序视为同一种方法,例如 2 + 2017 = 2019 与 2017 + 2 = 2019 视为同一种方法。

运行限制
最大运行时间:1s
最大运行内存: 128M

分析:

这道题目一开始看到就想着用一下搜索,先利用欧拉筛打出素数表,主循环for这些素数的下标,然后在递归函数中要记录该下标,递归函数中需要拿着这个下标之后的数来进行计算,然后就是一些常规的剪枝,最后却跑不出来结果,说明,虽然就是区区2019这么一个数,但是组成它的若干个互不相同的质数的和的情况还是很多的。因此需要转变思路。

这里的题目说了这道题,视2+2017和2017+2为同一种情况,而且强调了每个质数都互不相等,因此我们可以把问题转化为01背包问题,把2019看做是背包总容量,将素数当做是物品代价也就是容量,下面直接给出空间优化的滚动数组写法了。

#include
#define ll long long
using namespace std;
int prime[2200],cnt;
bool isprime[2200];
ll f[2020];//这里开int就报错了,以后这种并不能确定全部都开long long
inline void solve(){
	memset(isprime,true,sizeof(isprime));isprime[1]=false;
	for(int i=2;i<=2019;++i){
		if(isprime[i])prime[++cnt]=i;
		for(int j=1;j<=cnt&&i*prime[j]<=2019;++j){
			isprime[i*prime[j]]=false;
			if(i%prime[j]==0)break;
		}
	}
}
int main(){
	solve();f[0]=1;
	for(int i=1;i<=cnt;++i){
		if(prime[i]>2019)break;
		for(int j=2019;j>=prime[i];--j)
			f[j]+=f[j-prime[i]];
	}
	printf("%lld\n",f[2019]);
}

你可能感兴趣的:(算法学习,蓝桥杯,c++,算法)