PAT 1103. Integer Factorization (30) DFS+树状数组。还是人家的代码好
2017-09-09 21:39
363 查看
1103. Integer Factorization (30)
时间限制1200 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue
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,也不过是k重for循环而已。算是最笨的办法,一组一组数据试的,应该有更好的方法。直接k重for循环,有一组会超时。改成树状数组就过了。
#include <iostream> #include<stdio.h> #include<string> #include<queue> #include<algorithm> #include<string.h> #include<vector> #include<map> #include<math.h> using namespace std; int n,k,p; int tree_array[500]={0}; int last[500]={0}; int summ(int x) { int a=0; while(x>0) { a+=tree_array[x]; x-=x&(-x); } return a; } void updata(int x,int y) { while(x<401) { tree_array[x]+=y; x+=x&(-x); } } struct ZZ { int s[500]; int sum; bool operator < (const ZZ &A) const { if(sum!=A.sum) return sum>A.sum; for(int i=1;i<=p;i++) if(s[i]!=A.s[i]) return s[i]>A.s[i]; } }node[5]; int edge; vector<ZZ> Q; int cc(int x) { int i=1; for(int s=0;s<p;s++) i*=x; return i; } int lav=2; void dfs(int ceng) { int lala; if(ceng==1) lala=edge; else lala=node[0].s[ceng-1]; for(int i=1;i<=lala;i++) { node[0].s[ceng]=i; if(ceng==5&&i>4) lav++; updata(ceng,cc(i)-last[ceng]); last[ceng]=cc(i); int sum=0; //for(int j=1;j<=ceng;j++) //用这个会超时,改用树状数组。 // sum+=cc(node[0].s[j]); sum=summ(ceng); if(sum>n) break; // if(sum==n&&ceng==k) //测试输出 // { // for(int i=1;i<=ceng;i++) // cout<<node[0].s[i]<<' '; // cout<<endl; // } if(ceng<k) dfs(ceng+1); else { if(sum==n) { node[0].sum=0; for(int bb=1;bb<=k;bb++) node[0].sum+=node[0].s[bb]; Q.push_back(node[0]); } } } } int main() { cin>>n>>k>>p; int x=1; while(x<=n) //这里必须是小于等于,不能是小于 { edge++; x=1; for(int i=0;i<p;i++) x*=edge; } edge--; dfs(1); if(Q.empty()) cout<<"Impossible"; else { sort(Q.begin(),Q.end()); cout<<n<<" = "; cout<<Q[0].s[1]<<'^'<<p; for(int i=2;i<=k;i++) cout<<" + "<<Q[0].s[i]<<'^'<<p; // printf(" + %d^%d",Q[0].s[i],p); } return 0; }
看了下别人的代码,原理一模一样,不过人家的优雅轻便了不知道多少。。羞愧
分析:dfs深度优先搜索。先把i从0开始所有的i的p次方的值存储在v[i]中,直到v[i]
> n为止。然后深度优先搜索,记录当前正在相加的index(即v[i]的i的值),当前的总和tempSum,当前K的总个数tempK,以及因为题目中要求输出因子的和最大的那个,所以保存一个facSum为当前因子的和,让它和maxFacSum比较,如果比maxFacSum大就更新maxFacSum和要求的ans数组的值。
在ans数组里面存储因子的序列,tempAns为当前深度优先遍历而来的序列,从v[i]的最后一个index开始一直到index
== 1,因为这样才能保证ans和tempAns数组里面保存的是从大到小的因子的顺序。一开始maxFacSum == -1,如果dfs后maxFacSum并没有被更新,还是-1,那么就输出Impossible,否则输出答案。
#include <cstdio> #include <vector> #include <cmath> using namespace std; int n, k, p, maxFacSum = -1; vector<int> v, ans, tempAns; void init() { int temp = 0, index = 1; while(temp <= n) { v.push_back(temp); temp = pow(index, p); index++; } } void dfs(int index, int tempSum, int tempK, int facSum) { if(tempSum == n && tempK == k) { if(facSum > maxFacSum) { ans = tempAns; maxFacSum = facSum; } return ; } if(tempSum > n || tempK > k) return ; if(index >= 1) { tempAns.push_back(index); dfs(index, tempSum + v[index], tempK + 1, facSum + index); tempAns.pop_back(); dfs(index - 1, tempSum, tempK, facSum); } } int main() { scanf("%d%d%d", &n, &k, &p); init(); dfs(v.size() - 1, 0, 0, 0); if(maxFacSum == -1) { printf("Impossible"); return 0; } printf("%d = ", n); for(int i = 0; i < ans.size(); i++) { if(i != 0) printf(" + "); printf("%d^%d", ans[i], p); } return 0; }
相关文章推荐
- PAT 1057 Stack (30) (树状数组+二分 典型题)
- 1057. Stack (30)-PAT甲级真题(树状数组)
- PAT 1091. Acute Stroke (30) 3重方向并查集(其实非递归DFS也可以,,)
- USACO5.3 IDDFS_强连通_二维树状数组_斐蜀定理_矩形切割
- 【手动开栈】【dfs序】【树状数组】【Tarjan】bzoj2819 Nim
- hdu5156 Harry and Christmas tree 离线树状数组,dfs序
- [BZOJ2819]Nim-树状数组-dfs序
- 2016多校训练#5 1012 HDU 5792 树状数组 代码详解
- [poj 2352]Stars代码阅读记录[树状数组]
- PAT (甲)1004 Counting Leaves (30)(dfs)
- Poj3321 Apple Tree【DFS序】【树状数组】
- 1030. Travel Plan (30)-PAT甲级真题(Dijkstra + DFS,输出路径,边权)
- 【PAT 1001 Public Bike Management (30)】+ dfs + dijkstra
- PAT (Advanced Level)1030. Travel Plan (30) dfs
- bzoj 2434 (NOI2011)阿狸的打字机 【AC自动机】【树状数组】【DFS序】
- 【AC自动机】【树状数组】【dfs序】洛谷 P2414 [NOI2011]阿狸的打字机 题解
- BZOJ 1103 [POI 2007] dfs序+树状数组 解题报告
- 树状数组_应用的代码
- HDU5877 Weak Pair dfs + 线段树/树状数组 + 离散化
- 树状数组---原理代码实现