题目大意
给三个正整数N、K、P,将N表示成K个正整数的P次方和,其中,这K个正整数必须递减排列,允许重复,如果有多种方案,选择底数n1+…+nk最大的方案,如果还有多种方案,选择底数序列的字典序最大的方案。
思路解析
穷举法暴力模拟,为了避免超时,一般都把待选数放到一个数组里,而不是每次重新计算。我一开始以为给定第一个数的大小作为上界,剩余的数字在界内递归选择,第一次找到sum == n && deep == k的就是结果,然而会有超时,成功被PAT数据gank,所以以后还是乖乖的按照常规做法搞吧。
示例代码
#include<iostream>
#include<vector>
#include<math.h>
using namespace std;
int n, k, p,maxsum;
vector<int> v, res,res2;
void dfs(int index,int sum,int facsum, int deep) {
if (sum == n) {
if (facsum > maxsum && deep == k) {
maxsum = facsum;
res2 = res;
}
res.pop_back();
return;
}
for (int i = index; i > 0; i--) {
if (sum + v[i] <= n && deep + 1 <= k) {
res.push_back(i);
dfs(i, sum + v[i], facsum + i, deep + 1);
}
}
if (res.size() > 0) res.pop_back();
}
int main() {
scanf("%d %d %d", &n, &k, &p);
for (int i = 0; pow(i, p) <= n; i++)
v.push_back(pow(i, p));
dfs(v.size() - 1, 0, 0, 0);
if (res2.size() != k) {
printf("Impossible\n");
}
else{
printf("%d = %d^%d", n, res2[0], p);
for (int i = 1; i < res2.size(); i++)
printf(" + %d^%d", res2[i], p);
}
return 0;
}