2019蓝桥真题--质数拆分(动态问题01背包)

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

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

注:做题一定仔细读题,之前没看到两两不同,结果在哪里解了半天没解出来。

题解:
把2019拆分,反过来就是用若干个不同的质数组成值为2019的数。
每个数只取一次,刚好符合01背包问题。用f[i][j]表示用前i个数组成重量为j的方法数量,所以先打个素数表

优化后的素数筛:

public static void sushubiao() {
		a[1]=true;//false代表i为素数。
		for (int i = 2; i*i < a.length; i++) {
			if(!a[i]) {
				for(int j = i*i;j<a.length;j+=i) {
					a[j]=true;
				}
			}
			
		}
	}

打表:

int[] w = new int[2020];
		int k=1;
		for(int i =2;i<2020;i++) {
			if(!a[i]) {
				w[k++]=i;
			}
		}

实现01背包:如果不懂01背包点这里01背包的实现及优化
首先如果用i-1个数可以得到j,那么用i个数肯定也可以(因为数是从小到大排列,且i包含了[i-1]),所以每步要把f[i-1][j]赋值给f[i][j]

其次判断j是否大于w[i] 如果小于那么j里面肯定没有w[i]这个组成,例如j=7比w[i=5]小 (i代表是第五个质数w[5]=9),就不可以,如果是i=3,w[i]=5,f[3][7]就要加上f[2][7-5]

代码:

long[][] dp=new long[2030][2030];
		dp[0][0]=1;//dp[0][0]也是一种方法!!!!
		for(int i =1;i<k;i++) {
			for(int j=0;j<=2019;j++) {
				dp[i][j]=dp[i-1][j];
				if(j>=w[i]) {
					dp[i][j]+=dp[i-1][j-w[i]];
				}
			}
		}
		System.out.print(dp[k-1][2019]);

完整代码如下:(没有优化空间,优化空间上面链接有方法)

public class Zhishu_dp {
	static boolean[] a = new boolean[3000];
	static long res =0;
	public static void main(String[] args) {
		sushubiao();
		int[] w = new int[2020];
		int k=1;
		for(int i =2;i<2020;i++) {
			if(!a[i]) {
				w[k++]=i;
			}
		}
		long[][] dp=new long[2030][2030];
		dp[0][0]=1;//dp[0][0]也是一种方法!!!!
		for(int i =1;i<k;i++) {
			for(int j=0;j<=2019;j++) {
				dp[i][j]=dp[i-1][j];
				if(j>=w[i]) {
					dp[i][j]+=dp[i-1][j-w[i]];
				}
			}
		}
		System.out.print(dp[k-1][2019]);
		
	}
	public static void sushubiao() {
		a[1]=true;//false代表i为素数。
		for (int i = 2; i*i < a.length; i++) {
			if(!a[i]) {
				for(int j = i*i;j<a.length;j+=i) {
					a[j]=true;
				}
			}
			
		}
	}

}```

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值