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

Posted akcqhzdy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

 

以上是关于51nod 1642 区间欧拉函数 && codeforce594D REQ的主要内容,如果未能解决你的问题,请参考以下文章

51nod-1239&1244欧拉函数之和&莫比乌斯函数之和 杜教筛

51nod 1135 原根

欧拉函数之和 51Nod - 1239

51nod 1136 欧拉函数数论

51NOD-1136 欧拉函数

ACM学习历程—51NOD 1685 第K大区间2(二分 && 树状数组 && 中位数)