Pat(A) 1103. Integer Factorization (30)

本文介绍了一种通过深度优先搜索(DFS)算法实现的整数分解求解方法,旨在找到将给定正整数N表示为K个正整数的P次幂之和的方式,并确保这些正整数按非递增顺序排列且其总和最大。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题目:

原题链接:https://www.patest.cn/contests/pat-a-practise/1103

1103. Integer Factorization (30)


The K-P factorization of a positive integer N is to write N as the sum of the P-th power of K positive integers. You are supposed to write a program to find the K-P factorization of N for any positive integers N, K and P.

Input Specification:

Each input file contains one test case which gives in a line the three positive integers N (<=400), K (<=N) and P (1 < P<=7). The numbers in a line are separated by a space.

Output Specification:

For each case, if the solution exists, output in the format:

N = n1^P + … nK^P

where ni (i=1, … K) is the i-th factor. All the factors must be printed in non-increasing order.

Note: the solution may not be unique. For example, the 5-2 factorization of 169 has 9 solutions, such as 122 + 42 + 22 + 22 + 12, or 112 + 62 + 22 + 22 + 22, or more. You must output the one with the maximum sum of the factors. If there is a tie, the largest factor sequence must be chosen – sequence { a1, a2, … aK } is said to be larger than { b1, b2, … bK } if there exists 1<=L<=K such that ai=bi for ibL

If there is no solution, simple output “Impossible”.

Sample Input 1:
169 5 2
Sample Output 1:
169 = 6^2 + 6^2 + 6^2 + 6^2 + 5^2
Sample Input 2:
169 167 3
Sample Output 2:
Impossible

题目大意

输入N,K,P;
将N由K个数表示出来,这K个数必须是某个正整数的P次方。输出结果中K个数降序排列,如果存在多个,取使得K个正整数之和最大的那一组。

解题报告

DFS搜索结果,为节省时间,先将正整数的P次方存入数组factor中,上限为i^P<=N。主要代码dfs(n,maxnum,k)的作用是将n用k个不超过正整数为maxnum的P次方的数表示出来。
当n==k==0时,即达到要求了,判断答案是否更好,若好,则替换。
其中有两个剪枝操作
1. 若全部由K个最大正整数的P次方表示也不能达到n,那肯定没有解决方案,剪枝剪掉。

if(n > factor[maxnum] * k)
        return;
  1. 若n减去当前选择的正整数的P次方小于0,则肯定不会有结果,直接跳过。
 if(n - factor[i] < 0)
            continue;

本题警示

本人在此题上写了一个代码,第5个点总是过不去,经过两个晚上的debug,发现全局变量被修改了,原本init()函数里并没有“sumOfAns = 0;”这句代码,在执行第5个测试点时,init()执行完之后,sumOfAns的值就被修改为441,十分莫名其妙,故加上了一句。并写了一个博文以记录。
C++全局变量值被修改

代码

#include "iostream"
#include "math.h"
using namespace std;

int N,K,P;
int factor[20 + 1];
int maxNum;
int ans[400 + 5];
int sumOfAns = 0;
int tempAns[400 + 5];

void init(){
    cin>>N>>K>>P;
    maxNum = 1;
    factor[1] = 1;
    while(factor[maxNum] <= N){
        maxNum ++;
        factor[maxNum] = pow(maxNum * 1.0,P);
    }
    maxNum --;
    sumOfAns = 0;
}

void dfs(int n,int maxnum,int k){
    static int sum = 0;
    if(n > factor[maxnum] * k)
        return;
    if( ( n && (!k)) || ((!n) && k))
        return;
    int i;
    if(n == 0 && k == 0){
        if(sum > sumOfAns){
            for(int j = 1; j <= K; j++)
                ans[j] = tempAns[j];
            sumOfAns = sum;
        }
        return;
    }
    for(i = maxnum; i >= 1; i--){
        if(n - factor[i] < 0)
            continue;
        tempAns[K - k + 1] = i;
        sum += i;
        dfs(n - factor[i],i,k-1);
        sum -=i;
    }
}

void printAns(){
    if(!sumOfAns){
        cout<<"Impossible"<<endl;
        return;
    }
    cout<<N<<" = "<<ans[1]<<"^"<<P;
    for(int i= 2; i <= K; i++){
        cout<<" + "<<ans[i]<<"^"<<P;
    }
    cout<<endl;
}

int main(){
    init();
    dfs(N,maxNum,K);
    printAns();
    system("pause");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值