做惯了素数分解,其实直接因数分解,复杂度也是根号的,这非常有用.
筛是线性的,这也非常重要.
给出一段数,让你给出一个字典序大于他的最小数列.这种最小的大于..不是特别的东西.
每一个数放进来,素因数分解,如果和之前数没有重合,那么把他的新素因数都过一遍.
如果有了重合,那么就不行了.
这题说不出什么,感觉就是筛法的重现.搞不太清楚.
#include <iostream>
#include <cmath>
#include <cstring>
#include <vector>
using namespace std;
#define debug(x) //std::cerr << #x << " = " << (x) << std::endl
typedef long long LL;
const int MAXN = 5e6+17;
int a[MAXN],b[MAXN],vis[MAXN],visr[MAXN];
int prime[1100000],primesize=0;
bool isprime[11000000];
void sieve(int listsize){
memset(isprime, 1, sizeof(isprime));
isprime[1] = false;
for(int i=2;i<=listsize;i++){
if(isprime[i]) prime[++primesize]=i;
for(int j = 1; j <= primesize && i*prime[j] <= listsize;j++){
isprime[i*prime[j]] = false;
if(i%prime[j] == 0) break;
}
}
}
vector<int > dap(int x)
{
vector<int > vec;
int rt = sqrt(x);
if(isprime[x])
{
vec.push_back(x);
return vec;
}
for(int j=1;j<primesize;++j)
{
int p = prime[j];
if(p>rt) break;
if(x%p==0)
vec.push_back(p);
while(x%p==0)
x/=p;
}
if(x>1)
vec.push_back(x);
return vec;
}
int main(int argc ,char const *argv[])
{
#ifdef noob
freopen("Input.txt","r",stdin);freopen("Output.txt","w",stdout);
#endif
sieve(200017);
int n;
cin>>n;
for(int i=0;i<n;++i)
cin>>a[i];
int sup = 1;
bool have = false;
for(int i=0;i<n;++i)
{
if(have)
{
for(int j = sup+1;;++j)
{
if(!visr[j])
{
sup = j;
break;
}
}
vector<int > zt = dap(sup);
for(auto j : zt)
{
for(int k = j;k<=5e6;k+=j)
visr[k] = 1;
}
b[i] = sup;
continue;
}
vector<int > now = dap(a[i]);
debug(a[i]);
for(auto j : now)
{
if(vis[j])
have = true;
debug(j);
}
if(have)
{
int tmp;
for(int j = a[i]+1;;++j)
{
if(!visr[j])
{
tmp = j;
break;
}
}
vector<int > zt = dap(tmp);
for(auto j : zt)
{
for(int k = j;k<=5e6;k+=j)
visr[k] = 1;
}
b[i] = tmp;
}
else
{
for(auto j : now)
{
for(int k = j;k<=5e6;k+=j)
visr[k] = 1;
vis[j] = 1;
}
b[i] = a[i];
}
debug(b[i]);
}
for(int i=0;i<n;++i)
cout<<b[i]<<endl;
return 0;
}