• 51nod 1642 区间欧拉函数 && codeforce594D REQ


    画一下柿子就知道是求区间乘积乘区间内所有质因数的(p-1)/p(就是求欧拉的公式嘛)

    看上去莫队就很靠谱然而时间O(nsqrt(n)logn)并不资瓷

    还是离线,确定右端点,对于1~i的区间内的质因数我们在树状数组把他们插入到最后一次出现的位置,然后扫一次求逆元+找质因数O(nlog^2n)

    注意算质因子的时候不能用试除法啊

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const LL mod=1e9+7;
    int quick_pow(int A,int p)
    {
        int ret=1;
        while(p!=0)
        {
            if(p%2==1)ret=(LL)ret*A%mod;
            A=(LL)A*A%mod;p/=2;
        }
        return ret;
    }
    int inv(int A){return quick_pow(A,mod-2);}
    
    int pr,prime[1100000],pm[1100000];
    bool v[1100000];
    void get_prime()
    {
        pr=0;
        for(int i=2;i<=1001000;i++)
        {
            if(v[i]==false)prime[++pr]=i,pm[i]=i;
            for(int j=1;j<=pr&&i*prime[j]<=1001000;j++)
            {
                v[i*prime[j]]=true;
                pm[i*prime[j]]=min(pm[i],prime[j]);
                if(i%prime[j]==0)break;
            }
        }
    }
    
    int n;LL s[210000];
    int lowbit(int x){return x&-x;}
    void change(int x,LL k)
    {
        while(x<=n)
        {
            s[x]=s[x]*k%mod;
            x+=lowbit(x);
        }
    }
    LL getsum(int x)
    {
        LL ret=1;
        while(x>0)
        {
            ret=ret*s[x]%mod;
            x-=lowbit(x);
        }
        return ret;
    }
    
    int a[210000];LL sm[210000];
    struct query{int l,r,id;}q[210000];int as[210000];
    bool cmp(query q1,query q2){return q1.r<q2.r;}
    int last[1100000];
    int main()
    {
        get_prime();
        scanf("%d",&n);
        sm[0]=1;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]), sm[i]=sm[i-1]*a[i]%mod;
        int Q;
        scanf("%d",&Q);
        for(int i=1;i<=Q;i++)
            scanf("%d%d",&q[i].l,&q[i].r), q[i].id=i;
        sort(q+1,q+Q+1,cmp);
        
        int j=1;
        memset(last,0,sizeof(last));
        for(int i=1;i<=n;i++)s[i]=1;
        for(int i=1;i<=n;i++)
        {
            int d=a[i];
            while(d>1)
            {
                int p=pm[d];LL c=(LL)(p-1)*inv(p)%mod;
                if(last[p]>0)change(last[p],inv(c));
                last[p]=i;
                change(last[p],c);
                while(d%p==0)d/=p;
            }
            
            while(j<=Q&&q[j].r==i)
            {
                as[q[j].id]=sm[q[j].r]*inv(sm[q[j].l-1])%mod*getsum(q[j].r)%mod*inv(getsum(q[j].l-1))%mod;
                j++;
            }
        }
        
        for(int i=1;i<=Q;i++)printf("%d
    ",as[i]);
        return 0;
    }
  • 相关阅读:
    javaweb开发之解决全站乱码
    redis加入开机启动服务
    linux下安装memcache
    关于本地连接虚拟机(centos)里的mongodb失败问题
    oracle存储过程中返回一个程序集
    面向对象进阶(二)----------类的内置方法
    面向对象进阶(一)
    面向对象的三大特性之----------封装
    面向对象的三大特性之----------多态
    面向对象的三大特性之----------继承
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9887254.html
Copyright © 2020-2023  润新知