[BZOJ4026]dC Loves Number Theory(线段树)
根据欧拉函数的定义式可知,可以先算出a[l]*a[l+1]*...*a[r]的值,然后枚举所有存在的质因子*(p-1)/p。
发现这里区间中一个质因子只要计算一次,所以指计算“上一个同色点在区间外”的数。记录pre就是二维数点问题了,套路地用主席树即可。
被卡常。别的OJ过了BZOJ过不了,优化常数后别的OJ速度快一倍BZOJ还是过不了。
1 #include<cstdio> 2 #include<algorithm> 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 4 using namespace std; 5 6 const int N=50010,M=17000010,S=1000010,mod=1e6+777; 7 bool b[S]; 8 int n,Q,mx,nd,l,r,tot,ans,idx[S],lst[S],rt[N],a[N],sm[N],p[S],v[M],ls[M],rs[M]; 9 10 int ksm(int a,int b){ 11 int res=1; 12 for (; b; a=1ll*a*a%mod,b>>=1) 13 if (b & 1) res=1ll*res*a%mod; 14 return res; 15 } 16 17 int inv(int x){ return ksm(x,mod-2); } 18 19 void init(int n){ 20 rep(i,2,n){ 21 if (!b[i]) p[++tot]=i,idx[i]=tot; 22 for (int j=1; j<=tot && p[j]*i<=n; j++){ 23 b[p[j]*i]=1; 24 if (i%p[j]==0) break; 25 } 26 } 27 } 28 29 void ins(int &x,int y,int L,int R,int pos,int k){ 30 x=++nd; v[x]=v[y]; ls[x]=ls[y]; rs[x]=rs[y]; 31 if (L==R){ v[x]=1ll*v[x]*(k-1)%mod*inv(k)%mod; return; } 32 int mid=(L+R)>>1; 33 if (pos<=mid) ins(ls[x],ls[y],L,mid,pos,k); 34 else ins(rs[x],rs[y],mid+1,R,pos,k); 35 v[x]=1ll*v[ls[x]]*v[rs[x]]%mod; 36 } 37 38 int que(int x,int y,int L,int R,int pos){ 39 if (!x && !y) return 1; 40 if (L==R) return 1ll*v[y]*inv(v[x])%mod; 41 int mid=(L+R)>>1; 42 if (pos<=mid) return que(ls[x],ls[y],L,mid,pos); 43 else return 1ll*v[ls[y]]*inv(v[ls[x]])%mod*que(rs[x],rs[y],mid+1,R,pos)%mod; 44 } 45 46 int main(){ 47 scanf("%d%d",&n,&Q); sm[0]=1; v[0]=1; 48 rep(i,1,n) scanf("%d",&a[i]),sm[i]=1ll*sm[i-1]*a[i]%mod,mx=max(mx,a[i]); 49 init(mx); 50 rep(i,1,n){ 51 rt[i]=rt[i-1]; int t=a[i]; 52 for (int j=1; j<=tot && p[j]*p[j]<=t; j++) 53 if (t%p[j]==0){ 54 ins(rt[i],rt[i],0,n,lst[j],p[j]); lst[j]=i; 55 while (t%p[j]==0) t/=p[j]; 56 } 57 if (t>1) ins(rt[i],rt[i],0,n,lst[idx[t]],t),lst[idx[t]]=i; 58 } 59 rep(i,1,Q){ 60 scanf("%d%d",&l,&r); l^=ans; r^=ans; 61 printf("%d\n",ans=(1ll*sm[r]*inv(sm[l-1])%mod*que(rt[l-1],rt[r],0,n,l-1)%mod)); 62 } 63 return 0; 64 }