题目大意:将N分解为 N = n[1]^P + n[2]^P + ... + n[K]^P的形式。其中K和P是给定值。如果有多种分解,输出因子和最大的一种。如果仍有多种,输出因子字典序最大的一种。
本质上是取K个正数(可重复)使其和为N的问题,从1~N所有数的P次方,作为可选择的数。可以用dfs做。但是需要注意,因为要输出字典序最大的一种,应当从大的因子开始搜索,需要考虑factor数组的下标和大小的关系。如果下标大的值也大,那么dfs中index-1,递归边界是 index > 1;如果下标小的值大,那么dfs中index +1, 递归边界是 index < N。
取可重复数字的dfs写法还不熟练。
AC代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cmath>
#include<vector>
#include<algorithm>
#pragma warning(disable : 4996)
using namespace std;
void dfs(int index, int targetN, int targetK, int factorSum, int& maxFactorSum, vector<int>& factors, vector<int>& tmp, vector<int>& solution)
{
if (targetN == 0 && targetK == 0)
{
if (factorSum > maxFactorSum)
{
maxFactorSum = factorSum;
solution = tmp;
}
return;
}
if (targetN < 0 || targetK < 0 || index < 1) return;
tmp.push_back(index);
dfs(index, targetN - factors[index], targetK - 1, factorSum + index, maxFactorSum, factors, tmp, solution);
tmp.pop_back();
dfs(index - 1, targetN, targetK, factorSum, maxFactorSum, factors, tmp, solution);
}
int main()
{
int N, K, P;
scanf("%d%d%d", &N, &K, &P);
vector<int> factors = { 0 };
for (int i = 1; i <= N; i++)
{
if (pow(i, P) > N) break;
factors.push_back(pow(i, P));
}
vector<int> tmp, solution;
int maxFactorSum = 0;
dfs(factors.size() - 1, N, K, 0, maxFactorSum, factors, tmp, solution);
if (solution.empty()) printf("Impossible");
else
{
printf("%d = ", N);
for (int i = 0; i < K; i++)
{
printf("%d^%d", solution[i], P);
if (i < K - 1) printf(" + ");
}
}
system("pause");
return 0;
}