码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-11-01 11:34:44      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:space   ems   while   log   can   print   数组   color   a*   

画一下柿子就知道是求区间乘积乘区间内所有质因数的(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\n",as[i]);
    return 0;
}

 

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

标签:space   ems   while   log   can   print   数组   color   a*   

原文地址:https://www.cnblogs.com/AKCqhzdy/p/9887254.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!