CF959D Solution

题目链接

题解

对于\(b\)的3个限制,第1个仅由\(\not=a_i\)且字典位最高的\(b_i\)决定,第2个不要紧,第3个比较复杂。可以使用set维护当前全部满足第3个限制的\(b\)候选,埃氏筛求出\(b_i\)的全部质因数,并将其及其倍数于set中删除。如果每求出一个质因数均删除一遍时间不够,因此使用\(vis_i\)记录质因数\(i\)是否已由set中删除。若当前全部\(b_j=a_j\),为满足条件1需二分找出set中\(\ge a_i\)的最小\(b_i\),否则取最小\(b_i\)即可。

AC代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10,S=2e6;//S
int a[N],b[N]; bool vis[S];
set<int> s; 
int main()
{
	for(int i=2;i<=S;i++) s.insert(i);
	int n; bool flag=0;//flag=1/0:是/否已出现b[i]>a[i]
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
	{
		if(!flag) 
		{
			b[i]=*s.lower_bound(a[i]);
			if(b[i]>a[i]) flag=1;
		}
		else b[i]=*s.begin();
		s.erase(b[i]);
		int t=b[i];
		for(int j=2;j*j<=t;j++)
		{
			if(t%j) continue;
			if(!vis[j])
				for(int k=j;k<=S;k+=j) s.erase(k);
			vis[j]=1;
			while(t%j==0) t/=j;
		}
		if(t>1 && !vis[t])
			for(int k=t;k<=S;k+=t) s.erase(k);
		vis[t]=1;
	}
	for(int i=1;i<=n;i++) printf("%d ",b[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/violetholmes/p/14529909.html