https://pintia.cn/problem-sets/994805342720868352/problems/994805364711604224
要求寻找一个数列n1 n2 … nk
构造一棵子集数, 初始化后得到max_nk, 相当于从1~max_nk这max_nk个数中, 每个数可选可不选, 两个状态, 最后选k个数, 让他们满足条件.
关键在于dfs的两个分支:
//choose
path.push_back(num);
dfs(num,len+1,sum+powp[num],num_sum+num);
path.pop_back();
//not choose
if(num>1){
dfs(num-1,len,sum,num_sum);
}
选择, 则入栈. sum; num_sum; len 更新, 数字num不变, 可以继续选
不选择, 仅仅判断是否可以继续减少数字, 然后减少数字, 不做任何改变.
#include <bits/stdc++.h>
#define FF(a,b) for(int a=0;a<b;a++)
using namespace std;
int powp[1000];
int N,P,K;
int max_nk=1;
int max_num_sum=-1;
vector<int> path;
vector<int> ans;
int get_powp(int x){
int ans=1;
FF(i,P)
ans*=x;
return ans;
}
void init_powp(){
while(1){
powp[max_nk]=get_powp(max_nk);
if(powp[max_nk]>400)
break;
max_nk++;
}
}
void dfs(int num,int len,int sum,int num_sum){
if(sum>N || len>K) return;
if(sum==N && len==K){
if(num_sum>max_num_sum){
max_num_sum=num_sum;
ans=path;
}
return;
}
//choose
path.push_back(num);
dfs(num,len+1,sum+powp[num],num_sum+num);
path.pop_back();
//not choose
if(num>1){
dfs(num-1,len,sum,num_sum);
}
}
int main(){
// freopen("../in1","r",stdin);
cin>>N>>K>>P;
init_powp();
dfs(max_nk,0,0,0);
if(ans.size()){ //169 = 6^2 + 6^2 + 6^2 + 6^2 + 5^2
printf("%d = ",N);
FF(i,K){
printf("%d^%d",ans[i],P);
if(i!=K-1){
printf(" + ");
}
}
puts("");
} else
puts("Impossible");
}