2017 [六省联考] T2 相逢是问候

4869: [Shoi2017]相逢是问候

Time Limit: 40 Sec  Memory Limit: 512 MB
Submit: 1205  Solved: 409
[Submit][Status][Discuss]

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

HINT

 

 鸣谢多名网友提供正确数据,已重测!

 

Source

 
大家肯定都知道欧拉降幂公式了,就是x^y ≡ x^(y%p + [y>=p]*p )    mod p
这个厉害就厉害在可以在x和p不互质的情况下使用。
 
而且对于本题来说,我们可以发现一个位置最多被修改 log(P) 次就会永远成为一个定值。
所以我们暴力修改动态维护一下前缀和就好了。
 
注意,我们迭代的时候
 
#include<bits/stdc++.h>
#define ll long long
#define maxn 50005
using namespace std;
int P[30],n,m,a[maxn];
int f[maxn],len,C,opt,TP;
int le,ri,tim[maxn],val[maxn];
set<int> s;
//set<int> ::iterator it;

inline int add(int x,int y,const int ha){
	x+=y;
	return x>=ha?x-ha:x;
}

inline int mod(int x,int y,const int ha){
	ll P=x*(ll)y;
	return P>=ha?P%ha+ha:P;
}

inline int phi(int x){
	int y=1;
	for(int i=2;i*(ll)i<=x;i++) if(!(x%i)){
		y*=(i-1),x/=i;
		while(!(x%i)) x/=i,y*=i;
		if(x==1) break;
	}
	
	if(x!=1) return y*(x-1);
	else return y;
}

inline void update(int x,int y){
	for(;x<=n;x+=x&-x) f[x]=add(f[x],y,P[0]);
}

inline int query(int x){
	int an=0;
	for(;x;x-=x&-x) an=add(an,f[x],P[0]);
	return an;
}

inline int ksm(int x,int y,const int ha){
	int an=1;
	for(;y;y>>=1,x=mod(x,x,ha)) if(y&1) an=mod(an,x,ha);
	return an;
}

/*
int get(int sit,int pos){
	if(sit==TP) return a[pos]>=P[sit]?a[pos]%P[sit]+P[sit]:a[pos];
	else return ksm(C,get(sit+1,pos),P[sit]);
}
*/

inline void TOL(){
	int now=*s.lower_bound(le);
	for(;now<=ri;now=*s.upper_bound(now)){
		update(now,P[0]-val[now]);
		tim[now]++,TP=tim[now];
		
		if(tim[now]>len) val[now]=1;
		else val[now]=(a[now]>=P[TP]?a[now]%P[TP]+P[TP]:a[now]);
		for(int i=TP-1;i>=0;i--){
			val[now]=ksm(C,val[now],P[i]);
		}
		val[now]%=P[0];
		
		update(now,val[now]);
		
		if(tim[now]==len+1) s.erase(now);
	}
}

int main(){
//	freopen("9.in","r",stdin);
//	freopen("9.out","w",stdout);
	
	scanf("%d%d%d%d",&n,&m,P,&C);
	for(len=1;;len++){
		P[len]=phi(P[len-1]);
		if(P[len]==1) break;
	}
	s.insert(0),s.insert(n+1);
	for(int i=1;i<=n;i++){
	    scanf("%d",a+i);
		update(i,a[i]);
		s.insert(i);
		val[i]=a[i];
	}
	
	while(m--){
		scanf("%d%d%d",&opt,&le,&ri);
		if(opt) printf("%d\n",add(query(ri),P[0]-query(le-1),P[0]));
		else TOL();
	}
	
	return 0;
}

  

posted @ 2018-03-07 14:25  蒟蒻JHY  阅读(253)  评论(0编辑  收藏  举报