数论的题一窍不通
虽然这题这题只能算半个数论题
先 来 一 遍 欧 拉 筛 , 顺 便 记 录 z h i [ x ] 表 示 x 的 最 小 质 因 子 先来一遍欧拉筛,顺便记录zhi[x]表示x的最小质因子 先来一遍欧拉筛,顺便记录zhi[x]表示x的最小质因子
利 用 z h i [ x ] 数 组 可 以 快 速 分 解 质 因 子 利用zhi[x]数组可以快速分解质因子 利用zhi[x]数组可以快速分解质因子
对 于 已 经 选 择 的 数 , 标 记 所 有 质 因 子 , 表 示 后 续 不 能 选 这 个 质 因 子 了 对于已经选择的数,标记所有质因子,表示后续不能选这个质因子了 对于已经选择的数,标记所有质因子,表示后续不能选这个质因子了
Ⅰ . 当 前 字 典 序 还 未 分 胜 负 \color{Red}Ⅰ.当前字典序还未分胜负 Ⅰ.当前字典序还未分胜负
那 就 从 a i 这 个 数 开 始 , 暴 力 的 一 个 一 个 判 断 是 否 和 前 面 冲 突 那就从a_i这个数开始,暴力的一个一个判断是否和前面冲突 那就从ai这个数开始,暴力的一个一个判断是否和前面冲突
一 旦 发 现 不 冲 突 就 马 上 选 , 并 对 选 择 的 数 分 解 质 因 子 标 记 一旦发现不冲突就马上选,并对选择的数分解质因子标记 一旦发现不冲突就马上选,并对选择的数分解质因子标记
Ⅱ . 字 典 序 已 分 胜 负 \color{Red}Ⅱ.字典序已分胜负 Ⅱ.字典序已分胜负
直 接 从 最 小 质 因 子 往 上 看 找 到 第 一 个 每 个 被 选 择 的 质 因 子 直接从最小质因子往上看找到第一个每个被选择的质因子 直接从最小质因子往上看找到第一个每个被选择的质因子
为 啥 不 考 虑 和 数 ? 和 数 一 定 是 质 因 子 构 成 的 为啥不考虑和数?和数一定是质因子构成的 为啥不考虑和数?和数一定是质因子构成的
质 因 子 一 定 小 于 这 个 和 数 。 质因子一定小于这个和数。 质因子一定小于这个和数。
#include <bits/stdc++.h>
using namespace std;
const int inf=3e6+10;
const int maxn=1e5+10;
int flag,a[maxn],b[maxn];
int prime[inf+10],zhi[inf+10],n,top,use[inf+10];
bool vis[inf+10];
void make_prime()
{
for(int i=2;i<=inf;i++)
{
if( !vis[i] ) prime[++top]=i,zhi[i]=i;
for(int j=1;j<=top&&i*prime[j]<=inf;j++ )
{
vis[ i*prime[j] ]=1;
zhi[ i*prime[j] ]=prime[j];
if( i%prime[j]==0 ) break;
}
}
}
bool check( int x )
{
while( x>=2 )
{
if( use[ zhi[x] ] ) return false;
x/=zhi[x];
}
return true;
}
int main()
{
make_prime();
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
int j=1;
for(int i=1;i<=n;i++)
{
if( flag )//已分胜负,那么选最小的质数
{
while( use[ prime[j]] ) j++;
use[ prime[j] ]=1;
b[i]=prime[j];
}
else//未分胜负,暴力找大于a[i]且和前面不冲突的数
{
int k=a[i];
while( !check(k) ) k++;
if( k>a[i] ) flag=1;
b[i]=k;
while( k>=2 )//标记k的所有质因子
{
use[ zhi[k] ]=1;
k/=zhi[k];//分解素数
}
}
}
for(int i=1;i<=n;i++) cout << b[i] << " ";
}