bzoj 4026 dC Loves Number Theory(主席树)
题目链接:bzoj 4026 dC Loves Number Theory
题意:
给你n个数,有q个询问,每次问你一个区间乘积的欧拉函数。
强制在线。
题解:
由欧拉函数性质:
euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),其中p1,p2……pn为x的所有素因数
可知,我们需要维护一个区间的数的乘积的不同的质因数。
这里我就直接维护1-1/pi了,然后主席树维护一下这个东西,维护方式和用主席树维护区间不同的数都多少个类似。
然后对于每个数分解质因数,这里要预处理好。
用vector会T,最好用链表。
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 5 const int N=1e6+1000,P=1e6+777; 6 struct node{int l,r,pct;node(){pct=1;}}T[N*10]; 7 int n,q,cnt,x,l,r,f[N],root[N]; 8 int g[N],v[N*3],nxt[N*3],ed; 9 int ans,pct[N],inv[N]={0,1}; 10 bool vis[N]; 11 12 inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;} 13 14 void update(int pos,int val,int l,int r,int &x,int y) 15 { 16 T[x=++cnt]=T[y],T[x].pct=1ll*T[x].pct*val%P; 17 if(l==r)return; 18 int mid=l+r>>1; 19 if(pos<=mid)update(pos,val,l,mid,T[x].l,T[y].l); 20 else update(pos,val,mid+1,r,T[x].r,T[y].r); 21 } 22 23 int query(int rt,int L,int R,int l,int r) 24 { 25 if(L<=l&&r<=R)return T[rt].pct; 26 int mid=l+r>>1;int an=1; 27 if(L<=mid)an=1ll*an*query(T[rt].l,L,R,l,mid)%P; 28 if(R>mid)an=1ll*an*query(T[rt].r,L,R,mid+1,r)%P; 29 return an; 30 } 31 32 int main(){ 33 F(i,2,N) 34 { 35 if(vis[i])continue; 36 for(int j=i;j<N;j+=i) 37 vis[j]=1,adg(j,i); 38 } 39 F(i,2,N-1)inv[i]=1ll*inv[P%i]*(P-P/i)%P; 40 pct[0]=1,scanf("%d%d",&n,&q); 41 F(i,1,n) 42 { 43 scanf("%d",&x); 44 pct[i]=x,pct[i]=1ll*pct[i]*pct[i-1]%P; 45 int val=1; 46 for(int j=g[x];j;j=nxt[j]) 47 { 48 int it=v[j]; 49 val=1ll*val*(it-1)%P*inv[it]%P; 50 } 51 update(i,val,1,n,root[i],root[i-1]); 52 for(int j=g[x];j;j=nxt[j]) 53 { 54 int it=v[j]; 55 if(f[it]) 56 { 57 val=1ll*inv[it-1]*it%P; 58 update(f[it],val,1,n,root[i],root[i]); 59 } 60 f[it]=i; 61 } 62 } 63 F(i,1,q) 64 { 65 scanf("%d%d",&l,&r); 66 l^=ans,r^=ans; 67 ans=query(root[r],l,r,1,n); 68 ans=1ll*ans*pct[r]%P*inv[pct[l-1]]%P; 69 printf("%d\n",ans); 70 } 71 return 0; 72 }