By Jalan
知识工具需求
数学
数据结构和算法
- DFS
- DFS回溯
语言
题干
把N写成K个整数的^ P次方形式
(这个题操作一下就变成质因数分解,那就是另一个问题了)
输入条件
N<=400 K (≤N) P (1<P≤7)
输出条件
存在输出
N = n[1]^ P + … n[K]^ P
n[i]是1到n的第i个因数,要求非递增排序.
相等情况下输出K数和最大的,一致的情况输出较大序列
例子
例1
输入
169 5 2
输出
169 = 6^2 + 6^2 + 6^2 + 6^2 + 5^2
例2
输入
169 167 3
输出
Impossible
测试点
测试点2主要考察在sum出现tie的时候有没有按要求选择最大的sequence
题解
第一次
思路
参数的范围都是很小的,实际上考虑的也是小于400的数
不妨把x的P小于N-K的所有x和1存起来作为因数表.从中抽取K个看看合适不合适,抽取使用深搜加回溯.
把合适的存在一个result表里,在按照条件找出最合适的那个.
- 输入
- 存因数表.
- dfs答案.
这个dfs过程的实际改变量有:
1标记本次要选的位,控制dfs改变位置,同时也是dfs深度的nowKCounter
2这种dfs的固有属性nowSumOfKP,nowFactorSum和nowTest用于在每次dfs后判断本次结果是否采用,其实都可以通过nowTest得到
3nowSumOfKP也参与对DFS条件筛选
4index负责控制遍历,也参与条件筛选.
5直接用nowKCounter+1作为DFS的参数进行DFS,顺便避免了回溯时–; - 输出
预期时间复杂度
不知道
编写用时
超了不知道多久大概2小时吧.
代码
CPP
#include <algorithm>
#include <stack>
#include <stdio.h>
#include <vector>
using namespace std;
int N, K, P, maxFactorSum = -1;
bool cmp(int &a,int &b){
return a>b;
}
vector<int> factorList, result, nowTest;
void dfs(int nowSumOfKP, int nowFactorSum, int nowKCounter, int index)
{
if (nowKCounter == K)
{
if (nowSumOfKP == N && nowFactorSum > maxFactorSum)
{
result = nowTest;
maxFactorSum = nowFactorSum;
return;
}
if (nowSumOfKP == N && nowFactorSum == maxFactorSum)
{
int i=0;
while (i<K)
{
if (nowTest[i]==result[i])
{
++i;
continue;
}
break;
}
if (i==K)
{
return;
}
while (i<K)
{
if (nowTest[i]>result[i])
{
++i;
continue;
}
break;
}
if (i==K)
{
result=nowTest;
}
return;
}
return;
}
while (index >= 1) //一次while只找一位的数据.找到会进下一次dfs,找不到会return
{
if (nowSumOfKP + factorList[index] <= N)
{
nowTest[nowKCounter] = index;
dfs(nowSumOfKP + factorList[index], nowFactorSum + index, nowKCounter + 1, index);
// index不需要从factorList.size()开始,从自己开始就行
//factorList里存的数字的P次根号实际上是连续的,因为在factorList[0]处存了个0,所以实际上index的值就是factorList[index]的n次根号的值,所以nowFactorSum+个index就行了.
}
if (index == 1)
{
return;
}
index--; //在不是1且放不进去的时候index去找下一个.
}
}
int main(int argc, char const *argv[])
{
// 1
scanf("%d %d %d", &N, &K, &P);
//2
factorList.push_back(0); //让下标和数字对应
int i = 1;
while (1)
{
int temp = 1;
for (int j = 0; j < P; j++)
{
temp *= i;
}
i++;
if (temp <= N - K + 1)
{
factorList.push_back(temp);
}
else
{
break;
}
}
// 3
result.resize(K);
nowTest.resize(K);
int nowSumOfKP = 0;
int nowFactorSum = 0;
int nowKCounter = 0;
int index = factorList.size() - 1;
dfs(nowSumOfKP, nowFactorSum, nowKCounter, index);
if (maxFactorSum == -1)
{
printf("Impossible");
return 0;
}
// 4
int size = result.size();
printf("%d = %d^%d", N, result[0], P);
for (int i = 1; i < size; i++)
{
printf(" + %d^%d", result[i], P);
}
return 0;
}
运行用时
比柳神的稳定快10%,虽然不多但很开心.
结尾
看在我写了这么多注释的份上可以给我点个赞嘛,求求惹=]砰砰砰,给我加点写下去的油呀@.@
也欢迎关注我的CSDN账号呀,接下来两个月我应该会按这个格式更新所有的PTA甲级题目
**开心code每一天**