Solution P12524 [Aboi Round 1] I なんです

首先 gcd 的平方是骗人的,因为求的是积,平方最后乘上即可。

有一个 gcd 的转化:

\[\gcd(S)=\prod_{p\in\mathbb{P}}\prod_{k\ge 1,\forall x\in S,p_i^k|x}p_i \]

验证一下可以发现这是对的。

考虑对每个质数 \(p\) 统计答案。考虑枚举 \(p,k\),判断区间 \([l,r]\) 内有多少个数是 \(p^k\) 倍数(记为 \(c\)),根据组合数知识可得 \(c\) 中选奇数或偶数个的方案数是相等的。因此可行的 \(S\)\(2^{c-1}\) 个(\(c=0\) 时特判一下)。

但若对所有质数都扫一遍整个数组枚举答案不太牛。考虑经典 trick:记 \(V\) 表示值域上界,显然所有数都可以表示成若干个小于 \(\sqrt V\) 的质数和最多一个大于 \(\sqrt V\) 的质数的乘积。因此考虑根号分治。

大质数出现次数总和最多为 \(n\),且对应的 \(k\) 一定为 \(1\),这个随便拿个莫队维护区间内的 \(p^{(2^{cnt_p-1})}\) 就可以了。如果直接做可能是 \(O(n\sqrt q\log V)\) 的,因为要快速幂。可以套个离散对数板子做到 \(O(n\sqrt q)\)

小质数共有 \(O(\frac{\sqrt V}{\log V})\) 个。枚举每个小质数,然后 \(O(\log V)\) 枚举 \(k\),先扫一遍数组做前缀和,然后每个询问就可以 \(O(1)\) 查了。\(\log V\) 消掉了,总的时间复杂度是 \(O(q\sqrt V)\) 的。

\(n,q,V\) 同阶,时间复杂度 \(O(n\sqrt n)\)

const int N=100005,B=320,P=998244353;
vector<int>pr;
bool np[N];
int n,q,a[N],mxp[N],pw2[N],lg[N];
int id[N],cnt[N],ans[N],res=0;
il void add(int x){
    x=mxp[x];if(!x)return;
    if(cnt[x])res=(res-1ll*lg[x]*pw2[cnt[x]-1]%(P-1)+P-1)%(P-1);
    cnt[x]++;
    res=(res+1ll*lg[x]*pw2[cnt[x]-1])%(P-1);
}
il void del(int x){
    x=mxp[x];if(!x)return;
    res=(res-1ll*lg[x]*pw2[cnt[x]-1]%(P-1)+P-1)%(P-1);
    cnt[x]--;
    if(cnt[x])res=(res+1ll*lg[x]*pw2[cnt[x]-1])%(P-1);
}

struct Q{
    int l,r,i;
    il friend bool operator<(Q &x,Q &y){
        if(id[x.l]!=id[y.l])return x.l<y.l;
        else return (id[x.l]&1)?(x.r<y.r):(x.r>y.r);
    }
}qr[N];

signed main(){
    BSGS::init(3,P);
    forto(i,2,B){
        if(!np[i])pr.eb(i);
        for(int j:pr){
            if(i*j>B)break;
            np[i*j]=1;
            if(i%j==0)break;
        }
    }
    n=read(),q=read();
    pw2[0]=1;forto(i,1,n)pw2[i]=pw2[i-1]*2%(P-1);
    int x,mx=0;
    forto(i,1,n){
        x=a[i]=read(),id[i]=i/B,mx=max(mx,a[i]);
        for(int j:pr)while(x%j==0)x/=j;
        if(x>1){
            if(!lg[x])lg[x]=BSGS::qry(x);
            mxp[i]=x;
        }
    }
    forto(i,1,q)qr[i].l=read(),qr[i].r=read(),qr[i].i=i;
    sort(qr+1,qr+q+1);
    int l=1,r=0;
    forto(i,1,q){
        while(l>qr[i].l)add(--l);
        while(r<qr[i].r)add(++r);
        while(l<qr[i].l)del(l++);
        while(r>qr[i].r)del(r--);
        ans[qr[i].i]=res;
    }
    int k;
    for(int p:pr){
        k=BSGS::qry(p);
        for(int pk=p;;pk*=p){
            cnt[0]=0;
            forto(i,1,n)cnt[i]=cnt[i-1]+(a[i]%pk==0);
            forto(i,1,q){
                x=cnt[qr[i].r]-cnt[qr[i].l-1];
                if(x)ans[qr[i].i]=(ans[qr[i].i]+1ll*k*pw2[x-1])%(P-1);
            }
            if(1ll*pk*p>mx)break;
        }
    }
    forto(i,1,q)printf("%lld\n",fpow(3,ans[i]*2%(P-1),P));
    return 0;
}
posted @ 2025-05-26 13:49  UniGravity_qwq  阅读(22)  评论(0)    收藏  举报