idea
题意为对于正整数n分解为k个p次方的形式,若无,则输出impossible;若有,则输出底数和最大的方案,还有多种方案时则输出字典序最大(数值最大)的方案。
首先预处理所有p次方不大于n的值;
再用深搜枚举选择(可多次)或不选择当前底数的方案,当当前选择的底数个数nowK大于k或当前所选数的p次方nowSum大于n时停止,当nowK==k且nowSum= =n时找到一种方案,判断是否需要更新已有方案
solution
cpp
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
int n, k, p, sum = 0;
vector<int> fac, ans, temp;
void dfs(int index, int nowK, int nowSum, int facSum){
if(nowK == k && nowSum == n){//找到一种符合条件的组合
if(facSum > sum){//底数和更大则更新
sum = facSum;
ans = temp;
}
return;
}
if(nowK > k || nowSum > n) return;//不符合限制,剪掉
if(index > 0){//满足正整数,不需要考虑0
temp.push_back(index);
dfs(index, nowK + 1, nowSum + fac[index], facSum + index);//选择加入
temp.pop_back();//不加入则把上次选择加入时压入的index弹出
dfs(index - 1, nowK, nowSum, facSum);//选择不加入,考虑下一个底数
}
}
int main(){
scanf("%d%d%d", &n, &k, &p);
for(int i = 1, t = 0; t <= n; i++){//初始化p次方小于等于n的记录表
fac.push_back(t);
t = pow(i, p);
}
dfs(fac.size() - 1, 0, 0, 0);//倒着找,以字典序更大的为先
if(!sum) printf("Impossible");
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;
}