给你一个长度为 n 的序列 a,你需要依次把每个数染成红色或绿色,设 x 等于所有红色的数的乘积,y 等于所有绿色的数的乘积。一种染色方案是好看的当且仅当红色的数和绿色的数都至少有 1 个,并且 x 和 y 的最大公因数等于 1。 两种染色方案不同当且仅当存在一个数 ai 在两种方案里的颜色不同。 请你求出好看的染色方案数的二进制表示。
#include<bits/stdc++.h> usingnamespace std; int n,cnt,a[100005],t,mn[1000050],p[1000050],mx,f[1000050],mark[1000050]; voidinit(){ for (int i = 2; i <= mx; i++){ if (!mn[i]){ mn[i] = i; p[++t] = i; } for (int j = 1; j <= t; j++){ if (p[j] > mn[i] || p[j] > mx/i){ break; } mn[p[j]*i] = p[j]; } } } intfind(int x){ if (f[x] != x){ f[x] = find(f[x]); } return f[x]; } voidmer(int x,int y){ int a = find(x),b = find(y); if (a != b){ f[b] = a; } } intmain(){ //freopen(".in","r",stdin); //freopen(".out","w",stdout); scanf("%d",&n); for (int i = 1; i <= n; i++){ scanf("%d",&a[i]); mx = max(mx,a[i]); } init(); for (int i = 1; i <= mx; i++){ f[i] = i; } for (int i = 1; i <= n; i++){ int v = a[i]; if (v == 1){ cnt++; continue; } int last = 0; while (v > 1){ int now = mn[v]; while(v%now == 0){ v /= now; } if (last){ mer(last,now); } last = now; mark[last] = 1; } } for (int i = 1; i <= mx; i++){ if (mark[i] && f[i] == i){ cnt++; } } for (int i = 1; i <= cnt-1; i++){ printf("1"); } printf("0"); return0; }