蓝桥杯真题:质数拆分

这里,若干两两不同的质数之和,这里其实很容易想到首先我们要求出2019内的所有质数,这个打个表就好了,其次两两不同,我们应该要想到动态规划。

这里设dp[i][j]表示前i个质数,可以两两不同加起来等于j的方案数。

如果当前j>=prime[i],说明当前的质数可以取,取完后我们只要看j-prime[i]有多少种取法,那么方案数之中有部分为dp[i-1][j-prime[i]]种,另外一部分是不取当前的质数prime[i],即dp[i-1][j]。若j<prime[i],说明当前我们取不了prime[i],只有上面两种情况下的后一种即dp[i-1][j]。

其次,我们怎么初始化呢?我们初始化dp[0][0]=1,这样我们就能在第一次质数2的时候初始化了。

具体代码如下所示:

#include <iostream>
using namespace std;
#define N 2020
int prime[N];//质数表
int fg[N];
int cnt=0;
long long dp[N][N];
//挑选出小于等于2019的质数
void init()
{
  for(int i=2;i<=2019;i++)
	{
		if(!fg[i])
		{
			prime[++cnt]=i;
			for(int j=2;j*i<=2019;j++)
			{
				fg[j*i]=1;
			}
		}
	}
}
int main()
{
  // 请在此输入您的代码
  init();
  dp[0][0]=1;
  for(int i=1;i<=cnt;++i)
  {
    for(int j=0;j<=2019;++j)
    {
      //j<prime[i] 相当于当前最后一个质数取不了 相当于只能用前i-1个
      //j>=prime[j] 除了dp[i-1][j]可以取到j 
      //还能看dp[i-1][j-prime[i]]有多少种情况 这是算上了第i个质数的情况 
      dp[i][j]=dp[i-1][j];
      if(j>=prime[i])
      {
        dp[i][j]=dp[i-1][j]+dp[i-1][j-prime[i]];
      }
    }
  }
  cout<<dp[cnt][2019];
    // cout<<"55965365465060";
  return 0;
}


当然,我们还能减小空间复杂度,即滚动数组啥的,将main中的dp改成下面这种形式:

dp[0]=1;
	for(int i=1;i<=cnt;i++)
	{
		for(int j=2019;j>=prime[i];j--)
		{
			dp[j]=dp[j]+dp[j-prime[i]];//相当于dp[i-1][j]+dp[i-1][j-prime[i]] 
		}
	}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值