题目链接
实现方法
本题分为两步:
- 质因数分解;
- 数字重排序(相同数字不连续)
质因数分解使用线性筛法,并在求质因数的过程中不断减小原数字。
数字重排序与重排字符串方法相同。
- 使用有序集合multiset存放各质因数及其出现次数;
- 判断是否存在可行解(最多的次数ma是否超过总次数sum的一半,奇数为ma>sum/2+1);
- 先轮流输出次数最多和次数第二多的数字,直到最多的次数与第二多的次数相等;
- 循环依次输出剩余的所有数字(需要判断第3步输出的最后一个数字和第4步输出的第一个数字是否相同,相同需要交换顺序);
代码
#include <bits/stdc++.h>
using namespace std;
//输入的正整数范围超过了int的最大值,需要用long long
#define int long long
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n;
//使用map记录各质因数与其出现的次数
map<int,int>m;
cin>>n;
//1不是素数,需要特判
if(n==1)return cout<<-1,0;
for(int i=2;i*i<=n;i++){
while(n%i==0){
m[i]++;
n/=i;
}
}
if(n>1)m[n]++;
//使用multiset对质因数和出现次数重排序,并记录出现最多的次数
multiset<pair<int,int>>s;
int sum=0,ma=0;
for(auto j:m){
sum+=j.second;
ma=max(ma,j.second);
s.insert({j.second,j.first});
}
//判断是否存在可行解
if(2*ma-1>sum)return cout<<-1,0;
cout<<sum<<endl;
if(s.size()==1){
cout<<(*s.begin()).second<<endl;
return 0;
}
int x;
//
while(sum>0){
auto temp=*s.rbegin();
s.erase(temp);
auto temp2=*s.rbegin();
s.erase(temp2);
if(temp.first!=temp2.first){
cout<<temp.second<<" ";
temp.first--;
if(temp.first){
cout<<temp2.second<<" ";
x=temp2.second;
temp2.first--;
}
else break;
s.insert(temp);
s.insert(temp2);
}
else{
s.insert(temp);
s.insert(temp2);
break;
}
sum--;
}
vector<pair<int,int>>v;
for(auto i:s){
v.push_back(i);
}
while(1){
int jud=0;
for(int i=v.size()-1;i>=0;i--){
if(v[i].first){
cout<<v[i].second<<" ";
v[i].first--;
jud=1;
}
}
if(!jud)break;
}
return 0;
}