【蓝桥】【洛谷】P2563 [AHOI2001]质数和分解(动态规划)

题目链接:https://www.luogu.org/problemnew/show/P2563

题目描述

任何大于 1 的自然数 n 都可以写成若干个大于等于 2 且小于等于 n 的质数之和表达式(包括只有一个数构成的和表达式的情况),并且可能有不止一种质数和的形式。例如,9 的质数和表达式就有四种本质不同的形式:

9 = 2 + 5 + 2 = 2 + 3 + 2 + 2 = 3 + 3 + 3 = 2 + 7 。

这里所谓两个本质相同的表达式是指可以通过交换其中一个表达式中参加和运算的各个数的位置而直接得到另一个表达式。

试编程求解自然数 n 可以写成多少种本质不同的质数和表达式。

输入输出格式

输入格式:

文件中的每一行存放一个自然数 n(2 < n < 200) 。

 

输出格式:

依次输出每一个自然数 n 的本质不同的质数和表达式的数目。

输入样例#1:

2

200

 

输出样例#1:

1

9845164

 

稍微分析

状态转移方程: f[j] = f[j] + f[j-prime[i]]

动态规划的题思路每次都不好讲清楚,感觉最重要的还是结合代码和状态转移方程来领悟啊

 

AC代码

#include <bits/stdc++.h>
using namespace std;

int f[201];//记录当前下标n的 本质不同的质数和,初始值全为0
int pri[201];//用来排除非质数,初始值全为0

void add(int x)
{
//当前不同的质数和f[i]由自身f[i]和i减去一个质数x(f[i-x]) 的 不同的质数和组成
	for(int i=x; i<=200; i++)
		f[i]+=f[i-x];
}
void init()
{
	f[0]=1;//很容易忘记,很重要!(本身的意义是:质数不拆封也算一种质数和) 
	for(int i=2; i<=200; i++) {
		if(!pri[i]) { //当前i为质数进入if语句
			add(i);
			for(int j=i*i; j<=200; j+=i) //巧妙去除非质数
				pri[j]=1;
		}
	}
}
int main()
{
	init();
	int n;
	while(cin>>n) {//这里实际不推荐这么写,毕竟也因此被T了好多次了 
		cout<<f[n]<<endl;
	}
	return 0;
}

 

代码2

和上面代码的主要区别在于:排除非质数的方法不同

#include <bits/stdc++.h>
using namespace std;

int f[201];//记录当前下标n的 本质不同的质数和,初始值全为0

bool if_prime(int n)
{
	//if(n<=1)  return false;
	for(int i=2; i*i<=n; i++) {
		if(n%i==0) return false;
	}
	return true;
}
void init()
{
	f[0]=1;//本身的意义是:质数不拆封也算一种质数和
	for(int i=2; i<=200; i++) {
		if(if_prime(i) ) { //当前i为质数进入if语句
			int x=i;
			for(int j=x; j<=200; j++)
				f[j]+=f[j-x];
		}
	}
}
int main()
{
	init();
	int n;
	while(cin>>n)
		cout<<f[n]<<endl;

	return 0;
}

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值