PAT A1103 Integer Factorization整数分解 (经典DFS优化)

题目

在这里插入图片描述
在这里插入图片描述

分析

题意

给定正整数N、K、P,将N表示成K个正整数(可以相同,递减排列)的P次方的和,即N=nP+…nkP。如果有多种方案,那么选择底数和n1+…+nK最大的方案,如果还有多种方案,那么选择底数序列的字典序最大的方案。

注意

多方案时判断是否更优的做法的时间复杂度最好是O(1),否则容易超时。因此必须在DFS的参数中记录当前底数之和facSum,避免在找到一组解时计算序列的底数之和。

代码及解析

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>


using namespace std;

vector<int> temp, final;        //temp记录当前选择  final最终符合条件的选择
int n, k, p;                    //n 被分解的数  k 分解数的个数  p次方
int maxSum = 0, maxNum;         //maxNum    可选择的最大数

//计算可选择的最大数
int calcNum()
{
    int ret;
    for (int i = 1; i < n; i ++ )
    {
        ret = 1;
        for (int j = 0; j < p; j ++ )
        {
            ret *= i;
        }
        
        if(ret >= n)
            return (i - 1);         //该数的p次方是小于且最接近n的数
        else
            continue;
    }
    return -1;
}

// step 当前在第几个数  sum 当前总和    num 当前选择的数    facSum 记录目前选择的所有数总和
void dfs(int step, int sum, int num, int facSum)
{
    if(step == k && sum == n)       //到最后一个数且总和满足条件
    {
        // int s;
        // for (int i = 0; i < static_cast<int>(temp.size()); i ++ )
        //     s += temp[i];
        if(facSum > maxSum)     //更新最大因数和(使用facSum取消循环优化时复)
        {
            maxSum = facSum;
            final = temp;       //记录结果
        }
        return;
    }
    
    // for (int i = num; i >= 1; i -- )
    // {
    //     if(pow(i, p) + sum > n)
    //         continue;
    //取消循环 使用num优化时复
    if(sum > n || step > k)  return;            //不满足条件直接return
    if(num - 1 >= 0)                            //边界条件 可选择的最小数为1
    {
        temp.push_back(num);
        //dfs(step + 1, sum + pow(i, p), i);
        dfs(step + 1, sum + pow(num, p), num, facSum + num);          //选分支
        temp.pop_back();
        dfs(step, sum, num - 1, facSum);                      //不选分支 则更新num 保留step(相当于外循环)
    }
    // }
}


int main()
{
    scanf("%d%d%d", &n, &k, &p);
    maxNum = calcNum();             //计算可选择的最大数
    if(maxNum == -1)
        printf("Impossible\n");
    
    dfs(0, 0, maxNum, 0);           //搜

    if(static_cast<int>(final.size()) == k)         //满足条件时打印
    {
        printf("%d = ", n);
        for (int i = 0; i < static_cast<int>(final.size()); i ++ )
        {
            printf("%d^%d", final[i], p);
            if(i != k - 1)
                printf(" + ");
        }
        printf("\n");
    }
    else
        printf("Impossible\n");
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值