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 = n[1]^P + ... n[K]^P
where n[i]
(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 i<L and aL>bL.
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
一、AC代码
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;
int ans[400+5]; //存放答案
int fac[400+5]; //存放因素n[k]
int temp[400+5]; //存放在dfs中不断更新的因素n[Nowk]
int N, K, P,Maxfac; //169(N)=6(n[1])^2(P) + 6^2 + 6^2 + 6^2 + 5(n[k])^2,Maxfac = 29
bool juge; //用来判断是否存在等式
//计算w的P次方
int Pow(int w){
int ans = 1;
for(int i=0; i<P; i++)
ans *= w;
return ans;
}
//打印
void Print()
{
printf("%d = %d^%d", N,ans[1],P);
for(int i=2; i<=K; i++)
printf(" + %d^%d", ans[i],P);
printf("\n");
}
//temp数组赋值给ans数组
void duplicate(int a[], int b[])
{
for(int i=1; i<=N; i++)
b[i] = a[i];
}
//!核心代码
void dfs(int Nowk, int index, int sum, int pl, int x)
{
if(sum>N || Nowk>K)
return;
if(sum==N && Nowk==K && pl>Maxfac)
{
juge = true;
duplicate(temp, ans);
Maxfac = pl;
return;
}
if(index-1 >=0) //题目中有要求,N必须是正整数且由正整数相加,当index>1时可以继续选择
{
temp[x] = index;
dfs(Nowk+1, index, sum+fac[index], pl+index, x+1);
dfs(Nowk, index-1, sum, pl, x);
}
}
int main(){
int t;
while(scanf("%d%d%d", &N, &K, &P)!=EOF)
{
juge = false;
for(int i=0; i<=400; i++)
{
t = Pow(i);
if(t<=N)
{
fac[i] = t;
}else{
t = i-1;
break;
}
}
dfs(0,t,0,0,1); //此处注意初始值
if(!juge)
printf("Impossible\n");
else
Print();
}
}
//使用<math>头文件中的pow()函数注意,double类型转为int会掉精度,所以最好自己写一个
二、思路
弄清楚此题的简单逻辑框架,就能够实现最重要的dfs()函数中的代码。每次到达fac中的元素值时,比如169关于P=2的底数最大值为13,那么对于13我们就有两种选择;第一就是选择13,把13^2=169加入到sum中,并将构成此元素的底数13(n[i]^p中的n[i])加入到facsum中,我们接下来再继续选择13作为底数看是否满足要求。第二就是不选择此元素,底数-1进入递归,下一次的dfs的底数就从12开始。
在这里为什么底数是-1呢?因为我们从最大可能的底数开始,比较容易得到最大的sumfac也就是最终的最大底数和的那一组式子构成最终的答案。
可能到这里还会有些模糊,我们大致的框架上再继续细化。
当我们如果选择此元素,那么递归中的参数包括Nowk,也就是我们现在是在选择式子中的第i个数(i=1,2,3...K)需要+1,代表我们选择的元素占了一个位置。参数中的index,也就是我们选择的底数,最开始是13,在下一次选择中不变仍然选入。参数中的sum,也就是现在式子中所有元素的和要使用sum = sum + fac[index]更新。参数中的pl用来记录目前的式子中的底数和,最终覆盖形成我们最后的答案Maxfac,所以要更新为pl = pl + index。
如果我们发现加入此元素后导致sum>N 或者 Nowk>K 时,代表无答案,那么返回上一级到达下一个选项--不选择。不选择此元素,那么底数-1,sum、Nowk、pl都不变(没有加入元素当然不变),temp的下标也不变(如果不构成答案,那么当前位置可覆盖)。
三、收获
1. vector复习
2. dfs复习
3. 小细节,pow()函数赋值给int会导致精度丢失,计算的最终值错误。