【PAT A1103】Integer Factorization

在这里插入图片描述

类dfs递归
这个dfs最好有一个树在脑子里面,根节点不设任何东西,他的子节点为第一个位置可能的数,每个节点的子节点为不大于该节点的可能的数,节点的深度等于已经作为候选的数的个数

#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;


int N, K, P, maxfacsum = 0;
//fac[i]存放i^P,ans存放目前试的序列,res存放最终结果
vector<int> fac, ans, res;

void dfs(int factor, int nowK, int sum, int facsum){
	if(nowK == K && sum == N){
		if(maxfacsum < facsum){
			res = ans;
			maxfacsum = facsum;
		}
		return;
	}
	if(nowK > K || sum > N)
		return;
	if(factor > 0){
		ans.push_back(factor);
		dfs(factor, nowK + 1, sum + fac[factor], facsum + factor);
		ans.pop_back();
		dfs(factor - 1, nowK, sum, facsum);
	}
	else
		return;
}

int main(){
	scanf("%d%d%d", &N, &K, &P);
	
	int i = 0;
	while(1){
		int facPow = pow(i++, P);
		if(facPow <= N)
			fac.push_back(facPow);
		else
			break;
	}
	dfs(fac.size() - 1, 0, 0, 0);
	if(res.empty())
		printf("Impossible\n");
	else{
		printf("%d", N);
		for(int j = 0; j < res.size(); j++)
		{
			if(j == 0)
				printf(" = %d^%d", res[j], P);
			else
				printf(" + %d^%d", res[j], P);
		}
		printf("\n");
	}

	return 0;
}

非递归
基本思路就是从大往小的数试,如果当前正在试的数填满所有位置仍比目标总数小,那么再往小的数试就更不可能了(类似于剪枝),这时就要把前一个数减一重新试。(有点小复杂,我刚开始自己绕了好久)

#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;

int main(){
	int n, N, K, P;
	scanf("%d%d%d", &n, &K, &P);
	N = n;//后面要对n进行操作,所以暂存
	//fac[i]存放i^P,ans存放目前试的序列,res存放最终结果
	vector<int> fac, ans, res;
	int i = 0;
	while(1){
		int facPow = pow(i++, P);
		if(facPow <= N)
			fac.push_back(facPow);
		else
			break;
	}
	int maxsum = 0;
	i = fac.size();
	while(1){
		//insert
		//循环查找当前适合的最大数
		while(!(N >= 0 && N <= fac[i - 1] * (K - ans.size())) && i > 2)
			i--;
		//如果i >= 2而且ans里面尚有空位,则说明找到了可以放入ans的数
		if(i >= 2 && ans.size() < K){
			ans.push_back(i - 1);
			N -= fac[i - 1];
			//放入之后如果刚好符合要求,则判断是不是"最优"
			if(ans.size() == K && N == 0){
				int sum = 0;
				for(int j = 0; j < K; j++)
					sum += ans[j];
				if(sum > maxsum){
					maxsum = sum;
					res.clear();
					for(int j = 0; j < K; j++)
						res.push_back(ans[j]);
				}
			}
		}
		//否则说明没有找到合适的数
		else{
			//pop
			//如果ans是空的那么说明所有的可能已经试完了
			if(ans.empty())
				break;
			else{
				//把ans里的最后一个数减一重新试
				N += fac[ans[ans.size() - 1]];
				i = ans[ans.size() - 1];
				ans.pop_back();
			}
		}
	}
	if(res.empty())
		printf("Impossible\n");
	else{
		printf("%d", n);
		for(int j = 0; j < res.size(); j++)
		{
			if(j == 0)
				printf(" = %d^%d", res[j], P);
			else
				printf(" + %d^%d", res[j], P);
		}
		printf("\n");
	}
	return 0;
}```

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值