51nod 区间欧拉函数
链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1642
直觉离线。确实可以离线。
给定数组
a1,a2,a3,....,an
Q
询问。每次询问给定l,r 计算:
φ(∏i=lrai)
因为
φ(Pk)=Pk−Pk−1 , k>0φ(1)=1
所以:
P∣n 时:
φ(Pn)=Pφ(n)
P∤n 时:
φ(Pn)=(P−1)φ(n)
线段树离线处理即可。对询问按右端点排序
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define MAXN 1000005
#define MAXNN 200005
using 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;
}