51nod 1642 区间欧拉函数

来源:互联网 发布:seo关键词的布局原则 编辑:程序博客网 时间:2024/05/18 22:44

51nod 区间欧拉函数

链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1642

直觉离线。确实可以离线。

给定数组
a1,a2,a3,....,an

Q询问。每次询问给定l,r计算:

φ(i=lrai)

因为

φ(Pk)=PkPk1 , k>0φ(1)=1

所以:

Pn时:

φ(Pn)=Pφ(n)

Pn时:

φ(Pn)=(P1)φ(n)

线段树离线处理即可。对询问按右端点排序

#include <stdio.h>#include <string.h>#include <algorithm>#define MAXN 1000005#define MAXNN 200005using namespace std;typedef long long LL;struct Io{    char A[MAXN],*L,*R;    Io()    {        L=R=A;    }    void Io_fread()    {        L=A;        R=A+fread(A,sizeof(char),MAXN,stdin);    }    int read()    {        int tmp=0;        if(L==R)        {            Io_fread();            if(L==R)return tmp;        }        while(*L<'0'||*L>'9')        {            L++;            if(L==R)            {                Io_fread();                if(L==R)return tmp;            }        }        while(*L>='0'&&*L<='9')        {            tmp=tmp*10+ *L-'0';            L++;            if(L==R)            {                Io_fread();                if(L==R)return tmp;            }        }        return tmp;    }}I;const LL mod=1e9+7;struct node{    int w;    int c[2];    int a;    node()    {        a=1;        c[0]=c[1]=0;    }};struct Bt{    node A[MAXNN*3];    int deep;    int root;    int size;    Bt()    {        deep=2;        root=1;    }    void _insert(int l,int r,int L,int R,int &k,int key)    {        if(R<l||L>r)return ;        if(k==0)    k=deep++;        node &P=A[k];        if(l<=L&&R<=r)        {            P.a=(LL)P.a*key%mod;            return;        }        int mid=(L+R)>>1;        _insert(L,mid,L,mid,P.c[0],P.a);        _insert(mid+1,R,mid+1,R,P.c[1],P.a);        P.a=1;        _insert(l,r,L,mid,P.c[0],key);        _insert(l,r,mid+1,R,P.c[1],key);    }    void insert(int l,int r,int key)    {        _insert(l,r,0,size,root,key);    }    int _query(int x,int L,int R,int k)    {        if(x<L||x>R)return 1;        if(L==R)    return A[k].a;        node &P=A[k];        int mid=(L+R)>>1;        return (LL)_query(x,L,mid,P.c[0])*(LL)_query(x,mid+1,R,P.c[1])%mod*P.a%mod;    }    int query(int x)    {        return _query(x,0,size,root);    }}B;struct edge{    int a;    int k;    int next;    edge(){}}E[MAXN*4];int deep,inof[MAXN];void add(int a,int P,int k){    E[deep].a=P;    E[deep].k=k;    E[deep].next=inof[a];    inof[a]=deep++;}int data[MAXNN];int vis[MAXN],used[MAXN];struct QQ{    int l,r,i;    QQ(){}    bool operator <(const QQ &a)const    {        return r<a.r;    }}Q[MAXNN];int ans[MAXNN],tmp[MAXN];int main (){    //freopen("/Users/gaoxusheng/Desktop/In.txt","rw",stdin);    memset(inof,-1,sizeof inof);    int n;    n=I.read();    B.size=n;    for(int i=1;i<=n;i++)    {        data[i]=I.read();        vis[data[i]]=true;    }    for(int i=2;i<MAXN;i++)    {        if(used[i])continue;        add(i,i,1);        for(int j=i<<1;j<MAXN;j+=i)        {            used[j]=true;            if(!vis[j])continue;            int u=j,k=0;            while(u%i==0)            {                k++;                u/=i;            }            add(j,i,k);        }    }    int q=I.read();    for(int i=0;i<q;i++)    {        Q[i].l=I.read();        Q[i].r=I.read();        Q[i].i=i;    }    sort(Q,Q+q);    for(int i=0,x=1;i<q;)    {        while(x<=Q[i].r)        {            for(int d=inof[data[x]];d>-1;d=E[d].next)            {                edge &e=E[d];                B.insert(tmp[e.a]+1,x,e.a-1);                if(tmp[e.a])B.insert(0,tmp[e.a],e.a);                int k=1;                while(k<e.k)                {                    B.insert(0,x,e.a);                    k++;                }                tmp[e.a]=x;            }            x++;        }        int d=Q[i].r;        while(i<q&&Q[i].r==d)        {            ans[Q[i].i]=B.query(Q[i].l);            i++;        }    }    for(int i=0;i<q;i++)printf("%d\n",ans[i]);    return 0;}
原创粉丝点击