1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| #include<bits/stdc++.h> #define ll long long #define int long long #define ull unsigned long long #define maxn 50005 #define put() putchar('\n') #define Tp template<typename T> #define Ts template<typename T,typename... Ar> using namespace std; Tp void read(T &x){ int f=1;x=0;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();} x*=f; } namespace Debug{ Tp void _debug(char* f,T t){cerr<<f<<'='<<t<<endl;} Ts void _debug(char* f,T x,Ar... y){while(*f!=',') cerr<<*f++;cerr<<'='<<x<<",";_debug(f+1,y...);} #define gdb(...) _debug((char*)#__VA_ARGS__,__VA_ARGS__) }using namespace Debug; #define fi first #define se second #define mk make_pair
int calc(int n) { int ans=n,now=n,i; for (i=2;i*i<=n;i++) if (now%i==0) { ans=ans/i*(i-1); while (now%i==0) now/=i; } if (now>1) ans=ans/now*(now-1); return ans; } int n,m,p,c,g[maxn],a[maxn]; struct node { int Max,sum,nums; }f[maxn<<2]; void pushup(int rt) { f[rt].Max=max(f[rt<<1].Max,f[rt<<1|1].Max); f[rt].sum=(f[rt<<1].sum+f[rt<<1|1].sum)%p; } void build(int l,int r,int rt) { if (l==r) return f[rt].Max=1,f[rt].sum=a[l],void(); int mid=l+r>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); pushup(rt); } int L,flag=0; int pw1[105][10005],pw2[105][10005]; const int base=1e4; int power(int x,int y,int id) { return pw1[id][y%base]*pw2[id][y/base]%g[id]; } int F(int x,int n,int deep,int p) { if (p==1) { if (n==0&&a[L]==0) return 0; return flag=1,1; } if (n==0) { if (a[L]<p) return a[L]; else return a[L]%p+p; } int m=g[deep+1]; if (x==1) return flag=1,x; else { int tmp=F(x,n-1,deep+1,m),i,res=1; for (i=1;i<=tmp;i++) { res=res*x; if (res>p) return power(x,tmp,deep)+p; } return res; } } void Update(int l,int r,int rt,int head,int tail) { if (!f[rt].Max) return ; if (l==r) { L=l;flag=0; f[rt].nums++; int tmp=F(c,f[rt].nums,0,p)%p; if (flag) f[rt].Max=0; f[rt].sum=tmp; return ; } int mid=l+r>>1; if (head<=mid) Update(l,mid,rt<<1,head,tail); if (tail>mid) Update(mid+1,r,rt<<1|1,head,tail); pushup(rt); } int Query(int l,int r,int rt,int head,int tail) { if (head<=l&&r<=tail) return f[rt].sum; int mid=l+r>>1,res=0; if (head<=mid) res+=Query(l,mid,rt<<1,head,tail); if (tail>mid) res+=Query(mid+1,r,rt<<1|1,head,tail); return res%p; } signed main(void){ int i,op,l,r,j; read(n);read(m);read(p);read(c); g[0]=p; for (i=1;i<=100;i++) { g[i]=calc(g[i-1]); } for (j=0;j<=100;j++) { for (pw1[j][0]=1%g[j],i=1;i<=base;i++) pw1[j][i]=pw1[j][i-1]*c%g[j]; for (pw2[j][0]=1%g[j],i=1;i<=base;i++) pw2[j][i]=pw2[j][i-1]*pw1[j][base]%g[j]; } for (i=1;i<=n;i++) read(a[i]); build(1,n,1); while (m--) { read(op);read(l);read(r); if (op==0) Update(1,n,1,l,r); else printf("%lld\n",Query(1,n,1,l,r)); } cerr<<clock()*1.0/CLOCKS_PER_SEC<<endl; return 0; }
|