Topic meaning:
Maintain a sequence, support changing the number x in the interval to c^x, and sum the interval.
Solution:
Extended Euler's Theorem
a^b=a^(b%phi(p)+phi(p)) ( mod p )
Then because the base is determined, a number will not change at most log(x) times, because phi(p) becomes 1 after executing log(x) times
Line segment tree violence
Code:
#include<cstdio> #include<algorithm> using namespace std; int n,mod,c,m,p,cnt,a[1000005],phi[1000005],tree[1000005],minn[1000005]; int get_phi(int x){ int ans=x; for (int i=2; i*i<=x; i++) if (x%i==0){ years=years/i*(i-1); while (x%i==0) x/=i; } if (x!=1) ans=ans/x*(x-1); return ans; } void build(int t,int l,int r){ if (l==r){ tree[t]=a[l]; return; } int mid=(l+r)>>1; build(t<<1,l,mid); build(t<<1|1,mid+1,r); tree[t]=(tree[t<<1]+tree[t<<1|1])%mod; } int pow(int a,int b,int mod){ int ans=1; while (b){ if (b&1) ans=1ll*ans*a%mod; a=1ll*a*a%mod; b=b>>1; } return ans; } int query(int a,int times){ for (int i=times; i>=1; i--){ if (a>=phi[i]) a=a%phi[i]+phi[i]; a=pow(c,a,phi[i-1]); if (!a) a=phi[i-1]; } return a; } void change(int t,int l,int r,int x,int y){ if (l>y || r<x) return; if (minn[t]>=cnt) return; if (l==r){ from [t] ++; tree[t]=query(a[l],minn[t]); return; } int mid=(l+r)>>1; change(t<<1,l,mid,x,y); change(t<<1|1,mid+1,r,x,y); tree[t]=(tree[t<<1]+tree[t<<1|1])%mod; from [t] = min (from [t << 1], from [t << 1 | 1]); } int query (int t, int l, int r, int x, int y) { if (l>y || r<x) return 0; if (l>=x && r<=y) return tree[t]; int mid=(l+r)>>1; return (query(t<<1,l,mid,x,y)+query(t<<1|1,mid+1,r,x,y))%mod; } int main(){ scanf("%d%d%d%d",&n,&m,&p,&c); for (int i=1; i<=n; i++) scanf("%d",&a[i]); mod = phi [0] = p; while (p!=1){ phi[++cnt]=get_phi(p); p=phi[cnt]; } phi[++cnt]=1; build(1,1,n); while (m--){ int cas, l, r; scanf("%d%d%d",&cas,&l,&r); if (cas==0) change(1,1,n,l,r); else printf("%d\n",query(1,1,n,l,r)); } return 0; }