PAT1103
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 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
这是一道很考验dfs能力的题目。思路很简单,找到所有的数i(i^p<n) 然后对这个数集进行dfs。
我们来先看第一种写法
void dfs(int index,int sum,int num,int factsum)
{ if(sum==n&&num==k)
{ if(factsum>maxsum)
{
maxsum=factsum;
ans=temp;
}
else if(factsum==maxsum)
{ for(int i=;i<temp.size();i++)
{
if(temp[i]>ans[i])
{
ans=temp;
break;
}
else if(temp[i]<ans[i])
break;
}
}
return;
}
if(num>k||sum>n)
return; for(int i=index;i<=t;i++)
{
temp.push_back(v[i]); dfs(index+,sum+w[i],num+,factsum+v[i]); //每次允许重复的数字一定比第一个数字大,并且可以重复的次数与重复的数字有关。
temp.pop_back(); }*/
return;
}
过了一部分样例,但是仔细分析发现这种方式重复的数字是有限制的,第一个数只能重复两次,后面的数如果想要重复必须比第一个数字大,并且重复的次数也有要求。
例如对样例18 4 2就无法得到1 2 2 3因为比1大的数2最多只能重复(2-index)次,这里index为2
再看下一种写法:
void dfs(int sum,int num,int factsum)
{
if(sum==n&&num==k)
{
if(factsum>maxsum)
{
maxsum=factsum;
ans=temp;
}
else if(factsum==maxsum)
{ for(int i=;i<temp.size();i++)
{
if(temp[i]>ans[i])
{
ans=temp;
break;
}
else if(temp[i]<ans[i])
break;
}
}
return;
}
if(num>k||sum>n)
return;
for(int i=;i<=t;i++)
{
temp.push_back(v[i]); dfs(sum+w[i],num+,factsum+v[i]); //每次允许重复的数字一定比第一个数字大,并且可以重复的次数与重复的数字有关。
temp.pop_back(); }
return;
}
这种方法固然可行,但是肯定会超时。每次都重1开始计算,会出现大量重复的情况
void dfs(int index,int sum,int num,int factsum)
{
if(sum==n&&num==k)
{
if(factsum>maxsum)
{
maxsum=factsum;
ans=temp;
}
else if(factsum==maxsum)
{ for(int i=;i<temp.size();i++)
{
if(temp[i]>ans[i])
{
ans=temp;
break;
}
else if(temp[i]<ans[i])
break;
}
}
return;
}
if(num>k||sum>n)
return;
if(index>=)
{
temp.push_back(index);
dfs(index,sum+w[index],num+,factsum+v[index]);
temp.pop_back();
dfs(index-,sum,num,factsum);
}
/*for(int i=index;i>=1;i--)
{
temp.push_back(v[i]); dfs(index-1,sum+w[i],num+1,factsum+v[i]); //每次允许重复的数字一定比第一个数字大,并且可以重复的次数与重复的数字有关。
temp.pop_back(); }*/
return;
}
正解如上。从后往前递推,每个数字都可以重复多次,如果不符合条件就减1。同时这样相等时,第一个序列即为题目要求的输出。从前往后仍然可能会超时,因为初始的数字过于小了。
网上题解:
为了顺应题目找到最大系数和或者最大系数列,我们从小到大进行枚举,这样即使碰到了和相等的情况,由于是递增着枚举的,因此直接覆盖原来的系数列,得到的就是最终满足条件的系数列。
我们利用DFS来从小到大的枚举,DFS函数的参数如下:
dfs(long long N, int cur, vector<int>& factors);
①其中N是当前值,从最初的输入开始,逐步减去每个系数的运算结果;cur是枚举到的位置,从0开始,依次填入factors容器中,当cur==K时,枚举已经结束,我们判断N是否为0,为0则找到了一个满足条件的系数列,并且这个系数列按照升序存储在factors中。注意到cur==K但N≠0是我们的第一个剪枝条件。
②为了保证枚举从小到大开始,在每次枚举开始前计算lower和upper两个值,其中lower由factors中刚刚枚举完的上一个值确定,如果当前是枚举的起始点,则从1开始;upper为根号下N,因为系数的次方P>1,因此最大的系数不可能超过根号N。
③对lower到upper内的每一个值,计算系数的P次方,用res表示。如果N≥res,则说明合法,将其填入factors中并且向后枚举,即
- factors[cur] = i;
- dfs(N-res,cur+1,factors);
如果N<res,说明系数偏大,又因为系数是递增枚举的,所以此后都不满足,直接返回,这是我们的第二个剪枝条件。
综合上面两个剪枝条件,即可写出高效的dfs算法来枚举结果,为了能得到满足题目要求的系数列,我们设置全局变量nowSum和finalFactor,每次找到一个系数列,就求其系数和sum,如果sum≥nowSum,则更新nowSum与finalFactor,等号涵盖了题目中的第二个条件,因为后面出现的系数列一定大于前面出现的系数列(递增枚举)。
最后如果finalFactor规模为K,则说明找到,先反转,后输出,注意格式;否则输出Impossible。
这个题解是典型的剪枝方法
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm> using namespace std; typedef long long lint; lint N,K;
int P; lint lpower(lint n, lint p){
if(n == ) return ;
int factor = n;
for(int i = ; i < p; i++) n *= factor;
return n;
} vector<int> finalFactor;
int nowSum = ; bool dfs(lint N, int cur, vector<int>& factors){
if(cur == K){
if(N == ){
int sum = ;
for(int i = ; i < factors.size(); i++){
sum += factors[i];
}
if(sum >= nowSum){
finalFactor = factors;
nowSum = sum;
}
return true;
}else return false;
}
lint upper = sqrt((double)N);
lint lower = cur > ? factors[cur - ] : ;
for(lint i = lower; i <= upper; i++){
lint res = lpower(i,P);
if(N >= res){
factors[cur] = i;
dfs(N-res,cur+,factors);
}else{
return false;
}
}
return true;
} int main()
{
cin >> N >> K >> P;
vector<int> factors(K);
dfs(N,,factors);
reverse(finalFactor.begin(),finalFactor.end());
if(finalFactor.size() == K){
printf("%d = ",N);
printf("%d^%d",finalFactor[],P);
for(int i = ; i < finalFactor.size(); i++){
printf(" + %d^%d",finalFactor[i],P);
}
}else{
cout << "Impossible";
}
cout << endl; return ;
}
PAT1103的更多相关文章
随机推荐
- 在Windows系统上一批可以下载但是需要经过编译再安装的第三方的直接编译后的版本(UCI页面)
在Windows系统上一批可以下载但是需要经过编译再安装的第三方的直接编译后的版本(UCI页面) (https://www.lfd.uci.edu/~gohlke/pythonlibs/) win10 ...
- spring cloud之路(1)
1.各个功能 springcloud 注册中心 Eureka负载均衡 Ribbon路由网关 Zuul断路器 Hystrix分布式配置 config服务调用跟踪 sleuth日志输出 elk 认证集成 ...
- 2339 3.1.1 Agri-Net 最短网络
Description 农民约翰被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当然,他需要你的帮助. 约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享 ...
- mysql索引小结——高性能mysql
1.索引可以包含一个或者多个列的值,如果索引包含多个列的值,列的顺序很重要,mysql只能高效地使用索引的最左列前缀列. 2.索引是在存储引擎层而非服务器层实现的. 3.B-tree索引的限制: 如果 ...
- Cookie安全小结
Cookie机制:一般来说,同域内浏览器中发出的任何一个请求都会带上Cookie,无论请求什么资源,请求时,Cookie出现在请求头的Cookie字段中.服务端响应头的Set-Cookie字段可以添加 ...
- Haskell语言学习笔记(71)Semigroup
Semigroup class Semigroup a where (<>) :: a -> a -> a sconcat :: NonEmpty a -> a stim ...
- 5.Java中的数组.md
1.Java的数组定义 Java中的定义有两种形式: type[] arraryName; //推荐形式 type arrayName[]; //不推荐 前一种有更好的语义,可读性更好.但是需要注意的 ...
- eclipse 关于*.properties 文件 中文显示为Unicode,无法显示中文的问题(Properties Editor)
一.以下为在线安装Properties Editor的过程1.在eclipse下 "帮助"(help)--- 2.Install New Software3.Add4.Name:P ...
- ionic框架
ionic 是目前最有潜力的一款 HTML5 手机应用开发框架.通过 SASS 构建应用程序,它提供了很多 UI 组件来帮助开发者开发强大的应用. 它使用 JavaScript MVVM 框架和 An ...
- C# Excel导数据
遇到的几个坑,记录一下. 隐藏表,隐藏行,隐藏列, 单元格合并 => 拆分并填充内容, 显示隐藏列,结果那个列 还是不显示出来,拖动旁边的列也不显示. 结果在旁边的列上,按左右箭头键就出来了,也 ...