CF1028H Make Square
*2900!
典
考虑把每个数质因数分解,每个质数指数模 \(2\),对于 \(x,y\) 的答案是什么?是不是假如 \(2\) 边的质数指数只有 \(1\) 个为 \(1\) 的质数个数。
具体的,记 \(f_x\) 为 \(x\) 分解后指数模 \(2\) 为 \(1\) 的个数,那么 \(f_x+f_y\) 是不是 \(2\) 边同时为 \(1\) 就不需要减去?如何保留 \(2\) 边共同的 \(1\)?显然 \(\gcd(x,y)\),所以 \(ans=f_x+f_y-2f_{\gcd(x,y)}\)。
考虑 \(5e6\) 内质数个数最多 \(7\) 个,因为从 \(2\) 开始连续 \(8\) 个质数积大于 \(5e6\)。
那么 \(\max{d(a_i)}=2^7,i\in n\)。
接下来自然想到枚举 \(\gcd\),因为每个数的约数不多,显然需要上一个数 \(y,d|a_y\) 的位置,又因为答案跟 \(f\) 有关,\(f\) 最大为 \(7\),考虑扫描线,到 \(i\) 时枚举约数,再定义 \(f_{i,j}\) 为当前扫描下, \(\gcd\) 为 \(j\) 时,满足 \(j|a_x\) 的最大 \(x\)。那么只要枚举一下就好了,接下来变成一个更新操作有 \(n*7*128\) 次,查询操作有 \(m\) 次的单点更新,区间最小值,发现是不平衡的。我们直接使用 \(O(1)\) 修改,\(O(\sqrt{n})\) 查询分块即可。
这里补一个东西:
假如 \(\gcd(x,y)=d\),但是枚举到 \(k,k|d\) 时,因为 \(f_k<f_d\) 所以显然不会对最小值有影响。
不过确实跑的挺慢的(发现忘了关同步流,关了之后还是能在时限一半内通过的)。
#include <bits/stdc++.h>
//#define int long long
#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];
}
}
// ++mp[qwq]; if(mp[qwq]==2) vecd.pb(qwq);
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;
}