BZOJ 4026 dC Loves Number Theory (主席树+数论+欧拉函数)
题目大意:给你一个序列,求出指定区间的(l<=i<=r) mod 1000777 的值
还复习了欧拉函数以及线性筛逆元
考虑欧拉函数的的性质,(l<=i<=r),等价于 (p[j]是区间内所有出现过的质数)
那么考虑找出区间内所有出现过的质数,这思路和HH的项链是不是很像??
由于此题强制在线,所以把树状数组替换成了主席树而已
原来我以前写的主席树一直都是错的......还好推出了我原来错误代码的反例
在继承上一个树的信息时,注意不要破坏现在的树
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define ll long long 5 #define il inline 6 #define N 50010 7 #define maxn 1000000 8 #define mod 1000777 9 using namespace std; 10 11 int n,q,ctp,tot; 12 int root[N]; 13 int pr[maxn+100],use[maxn+100],lst[maxn+100]; 14 ll a[N],inv[mod+100],nxt[maxn+100]; 15 struct Seg{ll sum;int ls,rs;}seg[N*60]; //re 16 void prime_inv() 17 { 18 for(int i=2;i<=maxn;i++) 19 { 20 if(!use[i]) 21 pr[++ctp]=i,nxt[i]=i; 22 for(int j=1;j<=ctp&&i*pr[j]<=maxn;j++){ 23 use[i*pr[j]]=1,nxt[i*pr[j]]=pr[j]; 24 if(i%pr[j]==0) break; 25 } 26 } 27 inv[0]=inv[1]=1; 28 for(ll i=2;i<mod;i++) 29 inv[i]=(mod-mod/i)*inv[mod%i]%mod; 30 } 31 ll gc() 32 { 33 ll ret=0,fh=1;char p=getchar(); 34 while(p<'0'||p>'9') {if(p=='-')fh=-1;p=getchar();} 35 while(p>='0'&&p<='9') {ret=(ret<<3)+(ret<<1)+p-'0';p=getchar();} 36 return ret*fh; 37 } 38 il void pushup(int rt){seg[rt].sum=(seg[seg[rt].ls].sum*seg[seg[rt].rs].sum)%mod;} 39 void build(int l,int r,int rt) 40 { 41 seg[rt].sum=1; 42 if(l==r)return; 43 int mid=(l+r)>>1; 44 seg[rt].ls=++tot,build(l,mid,tot); 45 seg[rt].rs=++tot,build(mid+1,r,tot); 46 } 47 void update(int x,int l,int r,int rt1,int rt2,ll w) 48 { 49 if(l==r) {seg[rt2].sum=(seg[rt2].sum*w)%mod;return;} 50 int mid=(l+r)>>1; 51 if(x<=mid) 52 { 53 if(!seg[rt2].ls||seg[rt1].ls==seg[rt2].ls){ 54 seg[rt2].ls=++tot,seg[seg[rt2].ls].sum=seg[seg[rt1].ls].sum; 55 if(!seg[rt2].rs) 56 seg[rt2].rs=seg[rt1].rs; 57 } 58 update(x,l,mid,seg[rt1].ls,seg[rt2].ls,w); 59 }else{ 60 if(!seg[rt2].rs||seg[rt1].rs==seg[rt2].rs){ 61 seg[rt2].rs=++tot,seg[seg[rt2].rs].sum=seg[seg[rt1].rs].sum; 62 if(!seg[rt2].ls) 63 seg[rt2].ls=seg[rt1].ls; 64 } 65 update(x,mid+1,r,seg[rt1].rs,seg[rt2].rs,w); 66 } 67 pushup(rt2); 68 } 69 ll query(int L,int R,int l,int r,int rt) 70 { 71 if(L<=l&&r<=R) return seg[rt].sum; 72 int mid=(l+r)>>1;ll ans=1; 73 if(L<=mid) ans*=query(L,R,l,mid,seg[rt].ls),ans%=mod; 74 if(R>mid) ans*=query(L,R,mid+1,r,seg[rt].rs),ans%=mod; 75 return ans; 76 } 77 78 int main() 79 { 80 //freopen("a.in","r",stdin); 81 //freopen("a.out","w",stdout); 82 scanf("%d%d",&n,&q); 83 for(int i=1;i<=n;i++) a[i]=gc(); 84 prime_inv(); 85 root[0]=++tot; 86 build(1,n,1); 87 ll x,p,w; 88 for(int i=1;i<=n;i++) 89 { 90 x=a[i],w=a[i],root[i]=++tot; 91 while(x!=1){ 92 p=nxt[x]; 93 if(lst[p]) 94 update(lst[p],1,n,root[i-1],root[i],(inv[p-1]*p)%mod); 95 lst[p]=i; 96 x/=p,w=((w*(p-(ll)1)%mod)*inv[p])%mod; 97 while(x%p==0) x/=p; 98 } 99 update(i,1,n,root[i-1],root[i],w); 100 } 101 ll l,r,ans=0; 102 for(int i=1;i<=q;i++) 103 { 104 l=gc(),r=gc(); 105 l^=ans,r^=ans; 106 ans=query(l,r,1,n,root[r]); 107 printf("%lld\n",ans); 108 } 109 return 0; 110 }