1 条题解

  • 0
    @ 2025-8-24 22:06:48

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar mrsrz
    故障机器人

    搬运于2025-08-24 22:06:48,当前版本为作者最后更新于2018-12-09 20:20:39,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    在太阳西斜的这个世界里,置身天上之森。等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去、逐渐消逝的未来。我回来了,纵使日薄西山,即便看不到未来,此时此刻的光辉,盼君勿忘。————世界上最幸福的女孩

    我永远喜欢珂朵莉。


    10910^9以内的数最多有10个不同的质因子。

    考虑对其质因数分解。

    由于值域范围过大,考虑使用Pollard-Rho算法。

    这里普通的Pollard-Rho算法可能会TLE。如果你的代码能通过模板题,那基本上没问题(窝反正直接把以前写的板子拉过来然后调了调参)。

    之后,你就会得到最多10n10n个不同的质因数。对其进行离散化,开桶记录。

    然后上莫队,对于每次指针的偏移,把它所有的质因数加到桶里,同时维护约数个数即可。

    这部分时间复杂度O(10nn)O(10n\sqrt n),加上上面的质因数分解的玄学期望复杂度,只能获得82分的好成绩。


    我们考虑把每个数10001000以内的质因子先取出来(10001000以内共168个质数),然后,对其做前缀和,记录前缀的出现次数。

    然后,由于10013>1091001^3>10^9,所以每个数剩下最多不超过2个质因子。这部分用Pollard_Rho找即可。

    然后莫队的时候,对于前面168个质数就可以不用维护,直接用前缀和。

    而对于后面的大质因子,再离散化处理即可。由于每个数最多两个质因子,所以常数就小了很多。

    而由于筛掉了很多小的质因子,Pollard_Rho的速度也会变快。然后就足以通过此题。

    Code:

    #include<cctype>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<cstring>
    #define ctz __builtin_ctz
    using namespace std;
    #ifdef ONLINE_JUDGE
    struct istream{
        char buf[23333333],*s;
        inline istream(){
            buf[fread(s=buf,1,23333330,stdin)]='\n';
            fclose(stdin);
        }
        inline istream&operator>>(int&d){
            d=0;
            for(;!isdigit(*s);++s);
            while(isdigit(*s))
            d=(d<<3)+(d<<1)+(*s++^'0');
            return*this;
        }
    }cin;
    struct ostream{
        char buf[8000005],*s;
        inline ostream(){s=buf;}
        inline ostream&operator<<(int d){
            if(!d){
                *s++='0';
            }else{
                static int w;
                for(w=1;w<=d;w*=10);
                for(;w/=10;d%=w)*s++=d/w^'0';
            }
            return*this;
        }
        inline ostream&operator<<(const char&c){*s++=c;return*this;}
        inline void flush(){
            fwrite(buf,1,s-buf,stdout);
            s=buf;
        }
        inline~ostream(){flush();}
    }cout;
    #else
    #include<iostream>
    #endif
    int pri[170],cct=0,sum[100005][169],num[1005];
    void sieve(){
        for(int i=2;i<=1000;++i)num[i]=1;
        for(int i=2;i<=1000;++i)
        if(num[i]){
            pri[num[i]=++cct]=i;
            for(int j=i<<1;j<=1000;j+=i)num[j]=0;
        }
    }
    using LoveLive=long long;
    vector<int>tj;
    const int pr[]={2,3,5,7,11,13,17};
    int gcd(int a,int b){
        if(!a||!b)return a|b;
        int t=ctz(a|b);
        a>>=ctz(a);
        do{
            b>>=ctz(b);
            if(a>b)swap(a,b);
            b-=a;
        }while(b);
        return a<<t;
    }
    inline int power(int a,int b,const int&md){
        int ans=1;
        for(;b;b>>=1){
            if(b&1)ans=(LoveLive)ans*a%md;
            a=(LoveLive)a*a%md;
        }
        return ans;
    }
    int miller_rabin(int p){
        if(p==2)return 1;
        int b=p-1;
        int t=0;
        while(!(b&1))b>>=1,++t;
        for(int i:pr){
            int r=power(i%(p-2)+2,b,p);
            if(r==1||r==p-1)continue;
            int ok=1;
            for(int j=1;j<=t&&ok;++j){
                r=(LoveLive)r*r%p;
                if(r==p-1)ok=0;
            }
            if(ok)return 0;
        }
        return 1;
    }
    void pollard_rho(int&n,int c){
        int k=2,x=rand()%(n-1)+1,y=x,q=1,t=1;
        for(;;k<<=1,y=x,q=1){
            for(int i=1;i<=k;++i){
                x=((LoveLive)x*x%n+c)%n;
                q=(LoveLive)q*abs(x-y)%n;
                if(!(i&63)){
                    t=gcd(q,n);
                    if(t>1)break;
                }
            }
            if(t>1||(t=gcd(q,n))>1)break;
        }
        n=t;
    }
    void find(int n,int c){
        if(n==1)return;
        if(miller_rabin(n)){tj.push_back(n);return;}
        int p=n;
        while(p>=n)pollard_rho(p,c--);
        n/=p;
        tj.push_back(n),tj.push_back(p);
    }
    #define N 100005
    const int md=19260817;
    int n,m,a[N],inv[N*3],cnt[N],tot[N*2],now=1,ans[N];
    int p[N][3];
    vector<int>lr;
    struct que{
        static const int siz=317;
        int l,r,id;
        inline bool operator<(const que&rhs)const{
            return((l/siz!=rhs.l/siz)?(l<rhs.l):r<rhs.r);
        }
    }q[N];
    inline void add(int id){
        for(register int i=1;i<=cnt[id];++i)
        now=(LoveLive)now*inv[tot[p[id][i]]]%md*(tot[p[id][i]]+1)%md,++tot[p[id][i]];
    }
    inline void del(int id){
        for(register int i=1;i<=cnt[id];++i)
        now=(LoveLive)now*inv[tot[p[id][i]]]%md*(tot[p[id][i]]-1)%md,--tot[p[id][i]];
    }
    int main(){
        srand(19260817);
        sieve();
        cin>>n>>m;
        inv[1]=1;
        for(int i=2;i<=3*n;++i)inv[i]=(md-md/i)*1LL*inv[md%i]%md;
        for(int i=1;i<=n;++i){
            cin>>a[i];
            memcpy(sum[i],sum[i-1],sizeof*sum);
            for(int j=1;j<=cct&&pri[j]*pri[j]<=a[i];++j)
            while(!(a[i]%pri[j])){
                ++sum[i][j];
                a[i]/=pri[j];
            }
            if(a[i]>1){
                if(a[i]<=pri[cct]){
                    ++sum[i][num[a[i]]];
                    continue;
                }
                tj.clear();
                find(a[i],23333);
                for(int it:tj)
                p[i][++cnt[i]]=it,lr.push_back(it);
            }
        }
        sort(lr.begin(),lr.end());
        lr.erase(unique(lr.begin(),lr.end()),lr.end());
        for(int i=1;i<=n;++i)
        for(int j=1;j<=cnt[i];++j)p[i][j]=lower_bound(lr.begin(),lr.end(),p[i][j])-lr.begin();
        for(int i=1;i<=m;++i)cin>>q[q[i].id=i].l>>q[i].r;
        sort(q+1,q+m+1);
        for(int i=0;i<n<<1;++i)tot[i]=1;
        for(int i=1,l=1,r=0;i<=m;++i){
            while(r<q[i].r)add(++r);
            while(r>q[i].r)del(r--);
            while(l>q[i].l)add(--l);
            while(l<q[i].l)del(l++);
            int&out=ans[q[i].id];out=now;
            for(int j=1;j<=cct;++j)
            out=(LoveLive)out*(sum[r][j]-sum[l-1][j]+1)%md;
        }
        for(int i=1;i<=m;++i)
        cout<<ans[i]<<'\n';
        return 0;
    }
    
    • 1

    信息

    ID
    4092
    时间
    2500ms
    内存
    500MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者