#include<stdio.h> #include<iostream> #include<vector> using namespace std; int n,p,k; int facMaxSum = -1; vector<int>preData,ans,tmpAns; int power(int a,int b){ int sum = 1; while(b){ sum*=a; b--; } return sum; } int Preprocessing(){ int tmp = 0,index = 1; while(tmp<=n){//代码习惯,先判断,可以再插入 preData.push_back(tmp); tmp = power(index,p); index++; } } void dfs(int index,int tmpK,int tmpSum,int facMax){ if(tmpK == k){ if(tmpSum == n && facMax > facMaxSum){ ans = tmpAns; facMaxSum = facMax; } return ; } while(index >= 1){ if(tmpSum + preData[index]<=n){ tmpAns.push_back(index); dfs(index,tmpK+1,tmpSum+preData[index],facMax+index); tmpAns.pop_back(); } index--; } } int main() { cin>>n>>k>>p; Preprocessing(); dfs(preData.size()-1,0,0,0); if(facMaxSum == -1){ printf("Impossible"); return 0; } printf("%d =",n); for(int i=0;i<ans.size();i++){ printf(" %d^%d%s",ans[i],p,i ==ans.size()-1?"":" +"); } return 0; }
题目大意:
将整数N 分成 k 个幂次为p的数的和,如果有多个解,取底数和最大的解;
总结:
1.待取的元素是i^p,是离散的,在枚举解的过程中不好直接获取,所以,程序开始前先预处理,求出n以内的所有的i^p,让后通过下标即可枚举
2
int Preprocessing(){ int tmp = 0,index = 1; while(tmp<=n){//代码习惯,先判断,可以再插入 preData.push_back(tmp); tmp = power(index,p); index++; } }
3.
**错误1** 语句1 如果为真跳过这次循环,但是下标更新在语句2,程序进入死循环 while(index >= 1){ if(tmpSum + preData[index]>n)continue;//3. 当且仅当tempSum + v[index] <= n时,进行下一层的DFS,而不要进入下一层DFS发现不满足条件再返回,这样开销会比较大~ tmpAns.push_back(index); dfs(index,tmpK+1,tmpSum+preData[index],facMax+index); tmpAns.pop_back(); index--;//2 }
4
if(tmpSum + preData[index]<=n)// 当且仅当tempSum + v[index] <= n时,进行下一层的DFS,而不要进入下一层DFS发现不满足条件再返回,这样开销会比较大~
5
int facMaxSum = -1; //对于更优解的判断,初始化为不可能解,这样既可以判断是否有解,是否是更优解