相逢是问候
2017-09-09
Description
Informatikverbindetdichundmich.
信息将你我连结。B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数。一共有m个操作,可以分为两种:0 l r表示将第l个到第r个数(al,al+1,...,ar)中的每一个数ai替换为c^ai,即c的ai次方,其中c是输入的一个常数,也就是执行赋值ai=c^ai1 l r求第l个到第r个数的和,也就是输出:sigma(ai),l<=i<=rai因为这个结果可能会很大,所以你只需要输出结果mod p的值即可。
Input
第一行有三个整数n,m,p,c,所有整数含义见问题描述。
接下来一行n个整数,表示a数组的初始值。
接下来m行,每行三个整数,其中第一个整数表示了操作的类型。
如果是0的话,表示这是一个修改操作,操作的参数为l,r。
如果是1的话,表示这是一个询问操作,操作的参数为l,r。
1 ≤ n ≤ 50000, 1 ≤ m ≤ 50000, 1 ≤ p ≤ 100000000, 0 < c <p, 0 ≤ ai < p
Output
对于每个询问操作,输出一行,包括一个整数表示答案mod p的值。
Sample Input
4 4 7 2
1 2 3 4
0 1 4
1 2 4
0 1 4
1 1 3
Sample Output
0
3
1 40 19910626 2 0 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1 0 1 1 1 1 1
in_put
1 2 4 16 65536 11418102 18325590 13700558 13700558 13700558 13700558 13700558 13700558 13700558 13700558 13700558 13700558 13700558 13700558 13700558
out_put
考试时这个题感觉好神奇..当时某个学长将的时候一脸mengbier,整个人都noip了..什么事φ?
欧拉函数裸题,一个数c在mod一个数的时候,在最多log2p次会不变....
所以线段树维护区间和,区间修改最小值;
修改时遍历到每一个节点,暴力修改每一个改变的值,因为到一定的次数不会变,所以记录一个tag代表这个区间一共修改了多少次...
当l==r时就是那个点修改次数...最多log2p次就不用改了,时间复杂度n*2log(n)。记住,欧拉不要乱mod,会出事的...
#include<iostream> #include<cstdlib> #include<cstdio> #include<algorithm> #define ll (long long) #define LL long long #define IN int using namespace std; const IN maxn=50000+99; const IN N=10000+99; int read(){ int an=0,f=1; char ch=getchar(); while(!(‘0‘<=ch&&ch<=‘9‘)){if(ch==‘-‘)f=-f;ch=getchar();} while(‘0‘<=ch&&ch<=‘9‘){an=an*10+ch-‘0‘;ch=getchar();} return an*f; } IN phi[35],a[maxn],F; IN n,m,p,c; IN prime[maxn],isp[maxn],k,maxp;//k是质数个数,ips说明这是和数 struct saber{ IN sum,tag,l,r; }tr[maxn<<2]; IN Phi(IN x){ LL ans=x; for(IN i=1;i<=k && prime[i]*prime[i]<=x;i++){ if(!(x%prime[i]))ans=ans*(prime[i]-1)/prime[i]; while(!(x%prime[i]))x=x/prime[i]; } if(x>1)ans=ans/x*(x-1); return ans; } void euler(){ for(IN i=2;i<=N;i++){ if(!isp[i])k++,prime[k]=i; for(IN j=1;j<=k;j++){ if(i*prime[j]>N)break; isp[i*prime[j]]=1; if(!(i%prime[j]))break; } } phi[maxp]=p; while(phi[maxp]!=1)maxp++,phi[maxp]=Phi(phi[maxp-1]); maxp++; phi[maxp]=1; } void build(IN k,IN l,IN r){ tr[k].l=l; tr[k].r=r; if(l==r){ tr[k].sum=a[l]; return ; } IN mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum; } IN ask(IN k,IN i,IN j){ IN l=tr[k].l,r=tr[k].r; if(l==i&&r==j)return tr[k].sum; IN mid=(l+r)>>1; if(mid>=j)return ask(k<<1,i,j); else if(i>mid)return ask(k<<1|1,i,j); else return (ask(k<<1,i,mid)+ask(k<<1|1,mid+1,j))%p; } IN qw(LL k,IN mod){ LL ans=1;LL s=c; while(k){ if(k&1)ans*=s; k>>=1; s*=s; if(s>=mod)F=1,s%=mod; if(ans>=mod)F=1,ans%=mod; } return ans%mod; } LL work(LL a,LL t){ LL tmp=a; if(tmp>phi[t])tmp=tmp%phi[t]+phi[t]; for(IN i=t;i>0;i--){ F=0;tmp=qw(tmp,phi[i-1]); if(F)tmp+=phi[i-1],F=0; } return tmp; } void change(IN k,IN i,IN j){ if(tr[k].tag>=maxp)return; LL l=tr[k].l,r=tr[k].r; if(l==r){ tr[k].tag++; tr[k].sum=work(a[l],tr[k].tag)%p; return; } IN mid=(l+r)>>1; if(mid>=j)change(k<<1,i,j); else if(i>mid)change(k<<1|1,i,j); else {change(k<<1,i,mid);change(k<<1|1,mid+1,j);} tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum; tr[k].tag=min(tr[k<<1].tag,tr[k<<1|1].tag); } int main(){ n=read();m=read();p=read();c=read(); for(IN i=1;i<=n;i++)a[i]=read(); euler(); build(1,1,n); while(m) {m--; IN x,y,z; x=read();y=read();z=read(); if(x){ printf("%lld\n",ask(1,y,z)%p); } else { change(1,y,z); } } return 0; }
相逢是问候
by:s_a_b_e_r
时间: 2024-10-11 09:14:59