PAT A1103 Integer Factorization (!难***DFS)

问题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805364711604224

题意:

    给定正整数N, K, P,将N表示成K个正整数(可以相同,递减排序)的P次方的和,即N = n1^P+...nk^p。如果有多种方案,那么选择底数和n1+n2+...nk最大的方案;如果还有多种方案,那么选择底数序列的字典序最大的方案。

思路:

  1.     由于P大于1,并且在单词运行中是固定的,因此开一个vector<int> fac,在输入P之后就预处理出所有不超过N的n的P次方。即对N= 10,P = 2来说,fac[0] = 0, fac[1] = 1, fac[2] = 4, fac[3]=9...
  2.     DFS函数用于从fac中选择若干个数(可以重复选),使得它们的和等于N。于是需要针对fac中的每个数,根据选与不选这个数来进入两个分支,因此DFS的参数中必须有:(1)当前处理到的是fac的几号位,记为index;(2)当前已经选择了几个数,记为nowK。(3)当前选择出的数之和sum。(4)为了保证有多个方案时底数之和最小,还需在参数中记录当前选择出的数的底数之和facSum。————另外开一个vector<int> ans,用来存放最优的底数序列,用一个vector<int> temp存放当前选中的底数组成的临时序列
  3. 为让结果能保证字典序大的序列优先被选中,让index从大到小递减来遍历,这样就总是能选中fac中较大的数
#include<cstdio> 
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;

vector<int> fac, ans, temp;
int N, K, P, maxfacsum = 0;//maxfacsum记录最大底数之和 

//预处理fac数组 
void init(){
	int i = 1, temp = 0;
	while(temp <= N){//当i的P次方没有超过n时,不断把i的P次方加入fac 
		fac.push_back(temp);
		temp = pow(i, P);
		i++;
	}
}

//DFS函数,当前访问fac[index],nowK为当前选中个数
//sum为当前选中的数之和,facsum为当前选中的底数之和 
void DFS(int index, int nowK, int sum, int facsum){
	if(nowK == K && sum == N){
		if(facsum > maxfacsum){
			ans = temp;//更新最优底数序列,vector容器之间赋值
			maxfacsum = facsum;//更新最大底数和 
		}
		return;
	}
	if(sum > N || nowK > K)
	    return;
	if(index - 1 >= 0){//fac[0]不需要选择 
		temp.push_back(index);//把底数index加入临时序列temp
		DFS(index, nowK + 1, sum + fac[index], facsum + index);//选的分支 
		temp.pop_back();//选的分支结束把刚加进去的数pop掉
		DFS(index - 1, nowK, sum, facsum); //不选的分支 
	}
}
	
int main(){
	cin >> N >> K >> P;
	init();
	DFS(fac.size() - 1, 0, 0, 0);
	if(maxfacsum == 0)
	    cout << "Impossible"<<endl;
	else{
		printf("%d = %d^%d", N, ans[0], P);
		for(int i = 1; i < ans.size(); i++)
		    printf(" + %d^%d", ans[i], P);
	}
	return 0;
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值