1. 程式人生 > >Codeforces-959D Mahmoud and Ehab and another array construction task(貪心)

Codeforces-959D Mahmoud and Ehab and another array construction task(貪心)

題意:

給定陣列a,求大於或者等於陣列a字典序的陣列b,滿足任意i,j,gcd(bi, bj) = 1。並且是在所有滿足條件中的字典序最小的一個。

思路:

任意一對數互質,可以通過標記其質因子來解決,在找到第一個違背互質的數時,只需要找出大於該數的最小的一個與前面所有數互質的數,在此之後,要想保證字典序最小,便是所有可用的質數從小向大取。

程式碼:

#include <bits/stdc++.h>
using namespace std;
const int N = 3e6;
const int maxn = 1e5+5;
int prime[N+5], cnt;
bool isprime[N+5];
void prime_init() {
	for(int i = 2; i <= sqrt(N); ++i) {
		if(!isprime[i]) {
			for(int j = i*i; j <= N; j+=i) {
				isprime[j] = 1;
			}
		}
	}
	cnt = 0;
	for(int i = 2; i <= N; ++i) {
		if(!isprime[i]) {
			prime[++cnt] = i;
		}
	}
	// printf("%d\n", cnt);
}
int n, a[(int)1e5+5];
bool vis[N+5];
bool jg(int x, int flag) {
	for(int i = 1; i <= cnt && prime[i]*prime[i] <= x; ++i) {
		if(x % prime[i] == 0) {
			if(vis[prime[i]]) {
				return false;
			}
			if(flag) {
				vis[prime[i]] = 1;
			}
			while(x % prime[i] == 0) {
				x /= prime[i];
			}
		}
	}
	if(x > 1) {
		if(vis[x]) {
			return false;
		}
		if(flag) {
			vis[x] = 1;
		}
	}
	return true;
}
bool work(int id) {
	if(jg(a[id], 0)) {
		jg(a[id], 1);
		return false;
	}
	for(int i = a[id]+1; ; ++i) {
		if(jg(i, 0)) {
			jg(i, 1);
			a[id] = i;
			break;
		}
	}
	return true;
}
int main() {
	prime_init();
	scanf("%d", &n);
	int flag = 0, no = 1;
	for(int i = 1; i <= n; ++i) {
		scanf("%d", &a[i]);
		if(flag) {
			while(vis[prime[no]]) {
				++no;
			}
			a[i] = prime[no++];
			continue;
		}
		if(work(i)) {
			flag = 1;
		}
	}
	for(int i = 1; i <= n; ++i) {
		printf("%d%c", a[i], i==n?'\n':' ');
	}
	return 0;
}

繼續加油~