SOL:
p与a不互质时,设c=b mod φ(p)(专门设出来是因为公式不能正常显示),如果b>=φ(p):a^b≡a^(c+φ(p))
(注意b<φ(p)的时候再减φ(p))
我们可以证明 φ(p) 在 log次迭代后到达1,以后的数就不会对答案产生贡献。
那么我们暴力计算每个数的logn次操作,我们再用链表维护要修改的点,树状数组维护前缀和,即可。
当然我们可以打c的x次幂的表,省掉一个log
复杂度O(nlog^2)
#pragma comment(linker,"/stack:200000000") #pragma GCC optimize("-Os") #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") #include<bits/stdc++.h> using namespace std; #define sight(c) (‘0‘<=c&&c<=‘9‘) #define gc nc #define B 256 #define N 50007 #define LL long long #define L(x) x&-x int hea,head[N/B],n,op,pre[N],net[N],mo[N],p,m,c,l,r,ot,P[N],ptt; LL AA[N]; inline char nc(){ static char buf[1000000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++; } //int g[N][N/B]; int g[N],gg[N],tt[N]; int ff[B][10007],ggg[B][10007],ttt; inline void read(int &x){ static int b; static char c; for (b=1,c=gc();!sight(c);c=gc()) if (c==‘-‘) b=-1; for (x=0;sight(c);c=gc()) x=x*10+c-48; } inline void read(LL &x){ static int b; static char c; for (b=1,c=gc();!sight(c);c=gc()) if (c==‘-‘) b=-1; for (x=0;sight(c);c=gc()) x=x*10+c-48; } inline int Mo(LL x,int mo){return x<mo?x:x%mo+mo;} inline LL MO(LL x,LL mo) { x%=mo; if (x<0) x+=mo;return x;} LL orz; //inline int qsm(int x,int y,int& mo){ //// static int anw; //// for (anw=1;y;y>>=1,x=((orz=(LL)x*x)<mo?orz:orz%mo+mo)) //// if (y&1) anw=((orz=(LL)anw*x)<mo?orz:orz%mo+mo); //// return anw; // return Mo() //} inline LL te(int x){static LL q; for (q=0;x;x-=L(x)) q+=AA[x]; return q; } inline void ask(int x,LL dla){for (;x<N;x+=L(x)) AA[x]+=dla;} inline int fi(int x){ static int ple,anw; ple=sqrt(x); anw=1; for (int i=2;i<=ple;i++) if (x%i==0){ anw*=i-1; x/=i; while (x%i==0) x/=i,anw=anw*i; } if (x>1) anw=anw*(x-1); return anw; } void Pre(){ for (int i=1;i<=n;i++) pre[i]=i-1,net[i]=i+1; for (int i=n/B;~i;i--) head[i]=i*B; mo[0]=p; head[0]=1; for (int i=1;mo[i]=fi(mo[i-1]);i++) if (mo[i-2]==1) { ptt=i; break; } for (int i=ptt;~i;i--) { ff[i][0]=1; ggg[i][0]=1; for (int g=1;g<10000;g++) ff[i][g]=Mo((LL)ff[i][g-1]*c,mo[i]); ttt=Mo((LL)ff[i][9999]*c,mo[i]); for (int g=1;g<10000;g++) ggg[i][g]=Mo((LL)ggg[i][g-1]*ttt,mo[i]); } } inline void doo(int x,int y){ gg[x]=((tt[x]<mo[y])?tt[x]:tt[x]%mo[y]+mo[y]); //Mo(tt[x],mo[y]); for (int k=y;k;k--) gg[x]=//qs(gg[x],k-1); Mo((LL)ggg[k-1][gg[x]/10000]*ff[k-1][gg[x]%10000],mo[k-1]); gg[x]%=p; } void write(LL x){ if (x<10) { putchar(‘0‘+x);return; }write(x/10); putchar(x%10+‘0‘); } inline void writeln(LL x){write(x); putchar(‘\n‘);} signed main () { read(n); read(m); read(p); read(c); for (int i=1;i<=n;i++) read(gg[i]),gg[i]%=p,tt[i]=gg[i],ask(i,gg[i]); Pre(); while (m--) { read(op); if (op) { read(l);read(r); writeln(MO(te(r)-te(l-1),p)); } else{ read(l); read(r); hea=head[l/B]; while (hea< l) hea=net[hea]; while (hea<=r) { ot=++P[hea]; g[hea]=gg[hea]; doo(hea,ot); ask(hea,gg[hea]-g[hea]); if (ot>=ptt) { for (int t=n/B;~t;t--) if (head[t]==hea) head[t]=net[hea]; net[pre[hea]]=net[hea]; pre[net[hea]]=pre[hea]; } hea=net[hea]; } } } return 0; }