题意:
给定数组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;
}
继续加油~