[BZOJ4026]dC Loves Number Theory 尤拉函式+線段樹
阿新 • • 發佈:2018-11-06
題意:給定長度為 \(n\) 的序列 A,每次求區間 \([l,r]\) 的乘積的尤拉函式
題解
考慮離線怎麼搞,將詢問按右端點排序,然後按順序掃這個序列
對於每個 \(A_i\) ,列舉它的質因數,由於不同的質因數只算一次,所以我們只關心每個質數它最後一次出現的位置,開一棵線段樹維護一下每個位置的質數,加入新的質數時,先把之前的刪掉,再加新的
現在強制線上,可以開可持久化線段樹維護一下
#include<bits/stdc++.h> #define REP(i,a,b) for(int i(a);i<=(b);++i) #define dbg(...) fprintf(stderr,__VA_ARGS__) const int S=1<<18; char ibuf[S],*iS,*iT; #define gc (iS==iT?iT=ibuf+fread(iS=ibuf,1,S,stdin),iS==iT?EOF:*iS++:*iS++) inline int read(){char c,p=0;int w; while(isspace(c=gc));if(c=='-')p=1,c=gc;w=c&15; while(isdigit(c=gc))w=w*10+(c&15);return p?-w:w; } template<typename T,typename U>inline bool smin(T&x,const U&y){return x>y?x=y,1:0;} template<typename T,typename U>inline bool smax(T&x,const U&y){return x<y?x=y,1:0;} const int N=50005,M=1e6+999,p=1e6+777; int n,pr[1105],pre[M],inv[M],mul[N]; bool np[1105]; struct node{int ls,rs,w;}t[N*100]; int rt[N],cnt; inline void ins(int&o,int l,int r,int x,int v){ t[++cnt]=t[o];o=cnt;t[o].w=1ll*t[o].w*v%p; if(l==r)return;int mid=l+r>>1; x<=mid?ins(t[o].ls,l,mid,x,v):ins(t[o].rs,mid+1,r,x,v); } inline int ask(int o,int l,int r,int x){ if(x<=l)return t[o].w; if(x>r)return 1;int mid=l+r>>1; return 1ll*ask(t[o].ls,l,mid,x)*ask(t[o].rs,mid+1,r,x)%p; } signed main(){ n=read();int q=read(); REP(i,2,1100){ if(!np[i])pr[++pr[0]]=i; REP(j,1,pr[0]){ if(1ll*i*pr[j]>1100)break; np[i*pr[j]]=1; if(i%pr[j]==0)break; } } inv[0]=inv[1]=mul[0]=t[0].w=1; REP(i,2,p-1)inv[i]=1ll*(p-p/i)*inv[p%i]%p; REP(i,1,n){ int x=read();mul[i]=1ll*mul[i-1]*x%p;rt[i]=rt[i-1]; REP(j,1,pr[0]){ if(pr[j]*pr[j]>x)break; if(x%pr[j])continue; if(pre[pr[j]])ins(rt[i],1,n,pre[pr[j]],1ll*pr[j]*inv[pr[j]-1]%p); ins(rt[i],1,n,pre[pr[j]]=i,1ll*(pr[j]-1)*inv[pr[j]]%p); do x/=pr[j];while(x%pr[j]==0); } if(x>1){ if(pre[x])ins(rt[i],1,n,pre[x],1ll*x*inv[x-1]%p); ins(rt[i],1,n,pre[x]=i,1ll*(x-1)*inv[x]%p); } } int ans=0; while(q--){ int l=read()^ans,r=read()^ans; printf("%d\n",ans=1ll*mul[r]*inv[mul[l-1]]%p*ask(rt[r],1,n,l)%p); } return 0; }