题目大意:给定n个数,对于每个
a[i]
求一个最小的
j
,使得
首先这个式子对于每个
i
可以把
那么怎么预处理呢?
首先可以线性筛筛出f数组
然后对于每个i暴力更新它的约数的最小值就好啦!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 1000010
using namespace std;
bool he[N];
int a[N],p[N],f[N],cnt;
void getp()
{
int i,j;
for(i=2;i<=N-10;i++)
{
if(!he[i]) cnt++,p[cnt]=i,f[i]=1;
for(j=1;j<=cnt&&i*p[j]<=N-10;j++)
{
he[i*p[j]]=true;
f[i*p[j]]=f[i]+1;
if(i%p[j]==0) break;
}
}
}
int fir[N],sec[N];
void change(int x,int v)
{
if(fir[x]>N||f[a[v]]<f[a[fir[x]]])
{
sec[x]=fir[x];
fir[x]=v;
}
else if(sec[x]>N||f[a[v]]<f[a[sec[x]]]) sec[x]=v;
}
int main()
{
int n;
scanf("%d",&n);
int i,j;
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
getp();
memset(fir,0x3f,sizeof(fir));
memset(sec,0x3f,sizeof(sec));
for(i=1;i<=n;i++)
{
for(j=1;j*j<=a[i];j++)
if(a[i]%j==0)
{
change(j,i);
if(j*j!=a[i])
change(a[i]/j,i);
}
}
for(i=1;i<=n;i++)
{
int minn=707185547,minb;
for(j=1;j*j<=a[i];j++)
if(a[i]%j==0)
{
if(fir[j]!=i)
{
if(minn>(f[a[fir[j]]]-2*f[j]))
{
minn=(f[a[fir[j]]]-2*f[j]);
minb=fir[j];
}
else if(minn==(f[a[fir[j]]]-2*f[j])&&fir[j]<minb)
{
minn=(f[a[fir[j]]]-2*f[j]);
minb=fir[j];
}
}
else if(sec[j]<=N)
{
if(minn>(f[a[sec[j]]]-2*f[j]))
{
minn=(f[a[sec[j]]]-2*f[j]);
minb=sec[j];
}
else if(minn==(f[a[sec[j]]]-2*f[j])&&sec[j]<minb)
{
minn=(f[a[sec[j]]]-2*f[j]);
minb=sec[j];
}
}
if(fir[a[i]/j]!=i)
{
if(minn>(f[a[fir[a[i]/j]]]-2*f[a[i]/j]))
{
minn=(f[a[fir[a[i]/j]]]-2*f[a[i]/j]);
minb=fir[a[i]/j];
}
else if(minn==(f[a[fir[a[i]/j]]]-2*f[a[i]/j])&&fir[a[i]/j]<minb)
{
minn=(f[a[fir[a[i]/j]]]-2*f[a[i]/j]);
minb=fir[a[i]/j];
}
}
else if(sec[a[i]/j]<=N)
{
if(minn>(f[a[sec[a[i]/j]]]-2*f[a[i]/j]))
{
minn=(f[a[sec[a[i]/j]]]-2*f[a[i]/j]);
minb=sec[a[i]/j];
}
else if(minn==(f[a[sec[a[i]/j]]]-2*f[a[i]/j])&&sec[a[i]/j]<minb)
{
minn=(f[a[sec[a[i]/j]]]-2*f[a[i]/j]);
minb=sec[a[i]/j];
}
}
}
printf("%d\n",minb);
}
}