• 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
    ",add(query(ri),P[0]-query(le-1),P[0]));
    		else TOL();
    	}
    	
    	return 0;
    }
    

      

  • 相关阅读:
    (最小路径覆盖) poj 1422
    (匈牙利算法) hdu 2119
    (匈牙利算法) hdu 4185
    (匈牙利算法) hdu 2063
    (匈牙利算法)hdu 1281
    (匈牙利算法DFS)hdu 3729
    (01 染色判奇环) hdu 3478
    (多重背包)poj 1276
    (判断欧拉回路)poj 1368
    (差分约束) hdu 1384
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8522157.html
Copyright © 2020-2023  润新知