如果整个序列的GCD都不是1,直接输出不可以总司令就行了。

首先你发现一个很傻逼的性质是每个数只有最多2个有用,具体原因是因为一共两组,顶天一组一个。

所以你把那些出现次数多于2个的东西干成2个,然后随机一些序列跑贪心。

更具体地,你随一个序列,然后你贪心地选前面的数GCD起来直到它们的GCD是1,作为第一个序列;然后你去判断第二个序列的GCD是不是1就行了。

代码写的很答辩,轻喷。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<bits/stdc++.h>
using namespace std;
struct node{int x,id;bool operator<(const node &r)const{return x<r.x;}}a[100005],d[100005];
int n,b[100005],c[100005],m,e[100005];
mt19937 rd((unsigned long long)new char);
int gcd(int a,int b){return b?gcd(b,a%b):a;}
unordered_map<int,int> mp,mps;
int main(){
ios::sync_with_stdio(0);
cin>>n;
for(int i=1;i<=n;++i)cin>>d[i].x,d[i].id=i,e[i]=c[i]=d[i].x;
sort(d+1,d+n+1);
for(int i=1;i<=n;++i){
if(d[i].x==d[i-1].x&&d[i-1].x==d[i-2].x)continue;
b[++m]=d[i].x;c[m]=d[i].id;
}
int ans=0;
for(int i=1;i<=m;++i){a[i].x=b[i];a[i].id=c[i];ans=gcd(a[i].x,ans);}
sort(a+1,a+m+1);memset(b,0,sizeof b);
if(ans!=1){cout<<"NO\n";return 0;}
while(1.0*clock()/CLOCKS_PER_SEC<=0.48){
int sl=0,sr=0,j=1,id=1;
for(j=1;j<=m&&sl!=1;++j)sl=gcd(sl,a[j].x);
id=j-1;
for(;j<=m;++j)sr=gcd(sr,a[j].x);
if(sl==1&&sr==1){
for(int j=1;j<=id;++j)mp[a[j].x]=1,b[a[j].id]=1;
for(int j=id+1;j<=m;++j)mp[a[j].x]=2,b[a[j].id]=2;
for(int j=1;j<=n;++j)
if(!b[j])b[j]=mp[e[j]];
cout<<"YES\n";
for(int j=1;j<=n;++j)cout<<b[j]<<' ';
cout<<'\n';
return 0;
}
shuffle(a+1,a+m+1,rd);
}
cout<<"NO\n";
return 0;
}