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;
    }
}
原文地址:https://www.cnblogs.com/zcb123456789/p/13702419.html