1103 Integer Factorization (30分)[DFS][回溯]

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表里,在按照条件找出最合适的那个.

  1. 输入
  2. 存因数表.
  3. dfs答案.
    这个dfs过程的实际改变量有:
    1标记本次要选的位,控制dfs改变位置,同时也是dfs深度的nowKCounter
    2这种dfs的固有属性nowSumOfKP,nowFactorSum和nowTest用于在每次dfs后判断本次结果是否采用,其实都可以通过nowTest得到
    3nowSumOfKP也参与对DFS条件筛选
    4index负责控制遍历,也参与条件筛选.
    5直接用nowKCounter+1作为DFS的参数进行DFS,顺便避免了回溯时–;
  4. 输出

预期时间复杂度

不知道

编写用时

超了不知道多久大概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每一天**
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值