Loading

题解-CF1198F GCD Groups 2[*medium]

蒟蒻写了一个十分奇怪的不会证明正确性的随机化,竟然过了?感觉这个东西可以 hack 。。。

考虑最朴素的随机,每次 random_shuffle,随机取前缀作为第一个集合,剩下为第二个集合。

这个可以贪心来优化,每次 random_shuffle,让第一个集合为这个序列的最短的满足 \(\gcd\)\(1\) 的前缀,第二个集合为剩下的数。

发现这个东西 \(\tt WA\) 了。看看数据,发现是很多同样的数导致运行的效率极低!

发现很多个相同的数可以缩成两个数(因为一个在第一个集合,一个在第二个集合,其他都是没用的),然后就 \(\tt AC\) 了。。。。

代码:

#include<bits/stdc++.h>
#define L(i, j, k) for(int i = j, i##E = k; i <= i##E; i++)
#define R(i, j, k) for(int i = j, i##E = k; i >= i##E; i--)
#define ll long long
#define ull unsigned long long
#define db double
#define pii pair<int, int>
#define mkp make_pair
using namespace std;
const int N = 1e5 + 7;
inline int read() {
	int x = 0, f = 1; char ch=getchar();
	while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar();}
	while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
	return x * f; 
}
int n, ans[N], g[N], tot;
struct node {
	int val, id;
} f[N];
vector<int> ve[N];
map<int, int> A, B;
int main() {
	srand(233);
	const db st = clock();
	n = read();
	L(i, 1, n) {
		g[i] = read();
		if(!A[g[i]]) A[g[i]] = i, ++tot, f[tot].id = i, f[tot].val = g[i];
		else if(!B[g[i]]) B[g[i]] = i, ++tot, f[tot].id = i, f[tot].val = g[i];
		else ve[A[g[i]]].push_back(i);
	}
	while((clock() - st) / CLOCKS_PER_SEC < 0.4) {
		random_shuffle(f + 1, f + tot + 1);
		int now = 0, pp = 0, cnt = 0;
		L(i, 1, tot) {
			now = __gcd(now, f[i].val);
			if(now == 1) {
				++cnt;
				if(cnt == 2) {
					L(t, 1, pp) {
						ans[f[t].id] = 1;
						for(int p : ve[t]) ans[p] = 1;
					}
					L(t, pp + 1, n) {
						ans[f[t].id] = 2;
						for(int p : ve[t]) ans[p] = 2;
					}
					puts("YES");
					L(t, 1, n) printf("%d ", ans[t]);
					puts("");
					return 0;
				}
				pp = i, now = 0;
			}
		}
	}
	puts("NO");
	return 0;
} 
posted @ 2021-01-27 17:06  zhoukangyang  阅读(279)  评论(0编辑  收藏  举报