E. Decryption
题目链接:http://codeforces.com/contest/1419/problem/E
题意:给你一个合数n,用n大于1的因子围成一个圈,如果有两个相邻的数互质,那可以将那两个数的最小公倍数叉入中间,直到所有相邻的数都不互质为止。让你用n大于1的因子构造一个序列,以便使操作次数最少,输出序列以及最少操作次数即可。
思路:如果n仅仅是两个质因子的乘积时,他的任意一个序列都要操作1次才行;然后其他的都可以不需要进行操作,需要找到一种合适的就可以。可以用递归,每次加上的序列是以原有序列为基础的,把原来的序列反过来就可以保证加上后首位都是非互素相连的,再在中间加上一个1就可以把所有含有新的质因子的序列找出来即可。例如18=2*3*3;首先mp为空,我们把tmp上加上一个元素1后乘素因子2,mp变为{2};之后tmp为mp中间加个1后取逆为{2,1},依次乘上素因子3加到mp后面,mp变为{2,6,3};之后发现后面的还是3,就不急着进入下个递归,将tmp取逆,再依次乘上9加到mp后面,mp变为{2,6,3,9 ,18};
#include<bits/stdc++.h> using namespace std; typedef long long ll; vector<int> ve,mp; void dfs(int x) { vector<int> tmp=mp; if(tmp.empty()) tmp.push_back(1); else tmp.insert(tmp.end()-1,1); reverse(tmp.begin(),tmp.end()); while(1) { for(int i=0; i<tmp.size(); i++) mp.push_back(tmp[i]*ve[x]); x++; if(x==ve.size()) return; if(ve[x-1]%ve[x]==0) { ve[x]*=ve[x-1]; reverse(tmp.begin(),tmp.end()); } else break; } dfs(x); } int main() { int t; cin>>t; while(t--) { ve.clear(); mp.clear(); int n; cin>>n; for(int i=2; i*i<=n; i++) { while(n%i==0) { n/=i; ve.push_back(i); } } if(n!=1) ve.push_back(n); if(ve.size()==2&&ve[0]!=ve[1]) { cout<<ve[0]<<' '<<ve[1]<<' '<<ve[0]*ve[1]<<endl; cout<<1<<endl; continue; } dfs(0); for(int i=0; i<mp.size(); i++) cout<<mp[i]<<" "; cout<<endl; cout<<0<<endl; } }