*2900!
典
考虑把每个数质因数分解,每个质数指数模 2,对于 x,y 的答案是什么?是不是假如 2 边的质数指数只有 1 个为 1 的质数个数。
具体的,记 fx 为 x 分解后指数模 2 为 1 的个数,那么 fx+fy 是不是 2 边同时为 1 就不需要减去?如何保留 2 边共同的 1?显然 gcd(x,y),所以 ans=fx+fy−2fgcd(x,y)。
考虑 5e6 内质数个数最多 7 个,因为从 2 开始连续 8 个质数积大于 5e6。
那么 maxd(ai)=27,i∈n。
接下来自然想到枚举 gcd,因为每个数的约数不多,显然需要上一个数 y,d|ay 的位置,又因为答案跟 f 有关,f 最大为 7,考虑扫描线,到 i 时枚举约数,再定义 fi,j 为当前扫描下, gcd 为 j 时,满足 j|ax 的最大 x。那么只要枚举一下就好了,接下来变成一个更新操作有 n∗7∗128 次,查询操作有 m 次的单点更新,区间最小值,发现是不平衡的。我们直接使用 O(1) 修改,O(√n) 查询分块即可。
这里补一个东西:
假如 gcd(x,y)=d,但是枚举到 k,k|d 时,因为 fk<fd 所以显然不会对最小值有影响。
不过确实跑的挺慢的(发现忘了关同步流,关了之后还是能在时限一半内通过的)。
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=(int)(1e6+5),M=5040000;
bool vis[M];
int pri[M>>1],cnt;
int n,m,a[N],f[M];
namespace MI {
int mi[1000],val[N],id[N],bl,L[1000],R[1000];
void init() {
bl=sqrt(n);
for(int i=1;i<=n;i++) id[i]=(i-1)/bl+1;
for(int i=1;i<=id[n];i++) mi[i]=0x3f3f3f3f,L[i]=(i-1)*bl+1,R[i]=i*bl; R[id[n]]=n;
for(int i=1;i<=n;i++) val[i]=0x3f3f3f3f;
}
void upt(int x,int v) {
val[x]=min(val[x],v);
mi[id[x]]=min(mi[id[x]],v);
}
int qry(int l,int r) {
if(id[l]==id[r]) {
int res=0x3f3f3f3f;
for(int i=l;i<=r;i++) res=min(res,val[i]);
return res;
} else {
int res=0x3f3f3f3f;
for(int i=l;i<=R[id[l]];i++) res=min(res,val[i]);
for(int i=id[l]+1;i<id[r];i++) res=min(res,mi[i]);
for(int i=L[id[r]];i<=r;i++) res=min(res,val[i]);
return res;
}
}
}
void init() {
for(int i=2;i<=M-5;i++) {
if(!vis[i]) pri[++cnt]=i;
for(int j=1;j<=cnt&&pri[j]*i<=M-5;j++) {
vis[i*pri[j]]=1;
if(i%pri[j]==0) break ;
}
}
}
int gcd(int x,int y) {
return !y?x:gcd(y,x%y);
}
vector<pair<int,int> >vec[N];
int tmp[10],ans[N*5],sum[N],st[20][N];
vector<int>vecd[N];
inline int qry(int l,int r) {
int qwq=log2(r-l+1);
return min(st[qwq][l],st[qwq][r-(1<<qwq)+1]);
}
int mp[8][M];
signed main() {
cin.tie(0); ios::sync_with_stdio(false);
cin>>n>>m; init();
for(int i=1;i<=n;i++) {
int x,sz=0; cin>>x; int res=1;
for(int j=1;j<=cnt&&pri[j]*pri[j]<=x;j++) {
if(x%pri[j]) continue ;
int qwq=0;
while(x%pri[j]==0) x/=pri[j],++qwq;
if(qwq&1) tmp[++sz]=pri[j],res*=pri[j];
}
if(x!=1) res*=x,tmp[++sz]=x;
for(int S=1;S<=(1<<sz)-1;S++) {
int qwq=1;
for(int j=0;j<sz;j++) {
if((S>>j)&1) {
qwq*=tmp[j+1];
}
}
vecd[i].pb(qwq);
}
vecd[i].pb(1);
if(res!=1) a[i]=res;
}
for(int i=1;i<=M-5;i++) {
int x=i,num=0;
for(int j=1;j<=cnt&&pri[j]*pri[j]<=x;j++) {
if(x%pri[j]) continue ;
int qwq=0;
while(x%pri[j]==0) x/=pri[j],++qwq;
if(qwq&1) ++num;
}
if(x!=1) ++num;
f[i]=num;
}
memset(ans,0x3f,sizeof(ans));
memset(st,0x3f,sizeof(st));
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+(a[i]==0);
for(int i=1;i<=n;i++) {
if(!a[i]) st[0][i]=0x3f3f3f3f;
else st[0][i]=f[a[i]];
}
for(int i=1;(1<<i)<=n;i++) {
for(int j=1;j+(1<<i)-1<=n;j++) {
st[i][j]=min(st[i-1][j],st[i-1][j+(1<<(i-1))]);
}
}
for(int i=1;i<=m;i++) {
int x,y; cin>>x>>y;
if(sum[y]-sum[x-1]>=2) ans[i]=0;
else if(sum[y]-sum[x-1]==1) {
ans[i]=qry(x,y);
}
vec[y].pb(make_pair(x,i));
}
MI::init();
for(int i=1;i<=n;i++) {
for(int d:vecd[i]) {
for(int j=0;j<=7;j++) {
int p=mp[j][d];
if(p) MI::upt(mp[j][d],f[a[i]]+f[a[p]]-2*f[d]);
}
}
for(int d:vecd[i]) {
mp[f[a[i]]][d]=i;
}
for(auto x:vec[i]) ans[x.second]=min(ans[x.second],MI::qry(x.first,i));
}
for(int i=1;i<=m;i++) cout<<ans[i]<<'\n';
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】