扩展欧拉定理。
线段树维护,已经全改到底了的节点就不管,不然暴力修改下去。
//Achen #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<vector> #include<cstdio> #include<queue> #include<cmath> const int N=50000+7; #define For(i,a,b) for(int i=(a);i<=(b);i++) #define Rep(i,a,b) for(int i=(a);i>=(b);i--) typedef long long LL; using namespace std; LL n,m,p,pp,c,tp,cnt,phi[40],pr[40][N],pr2[40][N],mini[40]; template<typename T>void read(T &x) { char ch=getchar(); x=0; T f=1; while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘)) ch=getchar(); if(ch==‘-‘) f=-1,ch=getchar(); for(;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘; x*=f; } LL a[N],sg[N<<2],tot[N<<2]; int get_phi(int x) { int up=sqrt(x),rs=x; For(i,2,up) { if(!(x%i)) { rs=rs-rs/i; while(!(x%i)) x/=i; } } if(x!=1) rs=rs-rs/x; return rs; } LL get(int i,int a) { //c^a%phi[i] return pr2[i][a/pp]*pr[i][a%pp]%phi[i]; } #define lc x<<1 #define rc x<<1|1 #define mid ((l+r)>>1) void build(int x,int l,int r) { if(l==r) { sg[x]=a[l]; return; } build(lc,l,mid); build(rc,mid+1,r); sg[x]=(sg[lc]+sg[rc])%p; tot[x]=min(tot[lc],tot[rc]); } int lz[N<<1]; void down(int x,int l_len,int r_len) { if(!lz[x]) return; if(l_len) { sg[lc]=l_len*c%p; tot[lc]=cnt; lz[lc]=1; } if(r_len) { sg[rc]=r_len*c%p; tot[rc]=cnt; lz[rc]=1; } lz[x]=0; } void update(int x,int l,int r,int ql,int qr) { if(tot[x]>=cnt) return; if(l>=ql&&r<=qr&&l==r) { tot[x]++; sg[x]=a[l]>=phi[tot[x]+1]?a[l]%phi[tot[x]+1]+phi[tot[x]+1]:a[l]; Rep(i,tot[x],1) { int now=sg[x]>=mini[i]; sg[x]=get(i,sg[x]); if(now&&i!=1) sg[x]+=phi[i]; } return ; } if(ql<=mid) update(lc,l,mid,ql,qr); if(qr>mid) update(rc,mid+1,r,ql,qr); sg[x]=(sg[lc]+sg[rc])%p; tot[x]=min(tot[lc],tot[rc]); } LL qry(int x,int l,int r,int ql,int qr) { if(l>=ql&&r<=qr) return sg[x]; down(x,mid-l+1,r-mid); if(qr<=mid) return qry(lc,l,mid,ql,qr); if(ql>mid) return qry(rc,mid+1,r,ql,qr); return (qry(lc,l,mid,ql,qr)+qry(rc,mid+1,r,ql,qr))%p; } //#define DEBUG int main() { #ifdef DEBUG freopen("bzoj4869相逢是问候.in","r",stdin); freopen("bzoj4869相逢是问候.out","w",stdout); #endif read(n); read(m); read(p); read(c); For(i,1,n) read(a[i]); build(1,1,n); tp=p; phi[cnt=1]=tp; while(tp!=1) { phi[++cnt]=get_phi(tp); tp=phi[cnt]; } phi[++cnt]=1; phi[cnt+1]=1; pp=1e4; For(i,1,cnt) { tp=1; int tc=0; if(c!=1) { for(;;) { tp*=c; tc++; if(tp>=phi[i]) { mini[i]=tc; break; } } } else mini[i]=1e8; pr[i][0]=pr2[i][0]=1; For(j,1,pp) pr[i][j]=pr[i][j-1]*c%phi[i]; For(j,1,pp) pr2[i][j]=pr2[i][j-1]*pr[i][pp]%phi[i]; } if(c!=1) { mini[cnt]=1; mini[cnt-1]=0; } while(m--) { int o,l,r; read(o); read(l); read(r); if(!o) update(1,1,n,l,r); else printf("%lld\n",qry(1,1,n,l,r)%p); } return 0; }
原文地址:https://www.cnblogs.com/Achenchen/p/8604365.html
时间: 2024-10-04 03:44:08