如果整个序列的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; }
|