A. Array

https://codeforces.com/gym/102875/problem/A

p<=30

可以建立30颗线段树维护

然后看操作

一.add 懒标记

二.mul

三.mi 好像不能找到 (a+v)^{k}=?

于是懒标记貌似不能做,

但是考虑结果都要mod p,所以数都在0-p之间

其实就是i-> (操作)%p的映射

那就不用维护别的标记量了,直接映射

mi操作快速幂+拓展欧拉定理

答案可以是每个值的贡献

维护值的数量,开一个桶
维护值的映射位置,懒标记

// Problem: A. Array
// Contest: Codeforces - 2020 Jiangsu Collegiate Programming Contest
// URL: https://codeforces.com/gym/102875/problem/A
// Memory Limit: 1024 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<cstring>
#pragma GCC optimize(2)
#pragma GCC optimize("inline")
using namespace std;
typedef long long ll;
const int N=1e5+9;
int a[N],b[N],t[N]//暂时用;
int n,p;
int PHI;//phi(p)
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll phi(ll x){
	ll res=x;
	for(int i=2;i<=x/i;i++){
		if(x%i==0){
			res=res/i*(i-1);
			while(x%i==0){
				x/=i;
			}
		}
	}	
	if(x>1){
		res=res/x*(x-1);
	}
	return res;
}
ll qmi(ll a,ll b,ll mod){
	if(gcd(a,p)==1){//oulamo
		b%=PHI;
	}else if(b>=PHI){
		b%=PHI;
		b+=PHI;
	}
	ll res=1;
	while(b){
		if(b&1){
			res=res*a%mod;
		}
		a=a*a%mod;
		b>>=1;
	}
	return res;
}
//线段树
struct SEG{
    #define INF (1ll<<63)
    #define ll long long
    #define tl(id) (id<<1)
    #define tr(id) (id<<1|1)
    #define li inline
	struct Info{//信息
		ll num[33];
		li Info friend operator + (const Info &a,const Info &b){
			Info res;
			for(int i=0;i<p;i++){
				res.num[i]=a.num[i]+b.num[i];
			}
			return res;
		}
	};
	struct Tag{//标记
		ll tag[33];
		Tag(){init();}
		li void init(){
			for(int i=0;i<p;i++){
				tag[i]=i;
			}
		}
		li Tag(int *b){
			for(int i=0;i<p;i++){
				tag[i]=b[i];
			}
		}
		li Tag friend operator + (const Tag &a,const Tag &b){
			Tag t;
			for(int i=0;i<p;i++){
				t.tag[i]=b.tag[a.tag[i]];
			}
			return t;
		}
	};
    struct node{
    	int l,r;
    	Info val;
    	Tag lazy;
    }seg[N<<2];
    #define pushup(id) seg[id].val=seg[tl(id)].val+seg[tr(id)].val;
    li int inrange(int L,int R,int l,int r){return l<=L && R<=r;}
    li int outofrange(int L,int R,int l,int r){return L>r || R<l;}
    li void build(const int id,int l,int r){
        seg[id].l=l,seg[id].r=r;
        seg[id].lazy.init();
        if(l==r){
			seg[id].val.num[a[l]%p]++;           
            return;
        }
        int mid=(l+r)>>1;
        build(tl(id),l,mid);
        build(tr(id),mid+1,r);
        pushup(id);
    }
    li void maketag(int id,Tag v){
        int temp[33]={0};
        for(int i=0;i<p;i++){
        	temp[i]=seg[id].val.num[i];
        	seg[id].val.num[i]=0;
    	}
	    for(int i=0;i<p;i++){
	    	int k=v.tag[i];
	    	seg[id].val.num[k]+=temp[i];//i->k
	    }
    	seg[id].lazy=seg[id].lazy+v;//下传
    }
	 li void pushdown(int id){
    	int ok=0;
    	for(int i=0;i<p;i++){
    		if(seg[id].lazy.tag[i]!=i){
    			ok=1;
    		}
    	}	
    	if(ok){
			maketag(tl(id),seg[id].lazy);    		
			maketag(tr(id),seg[id].lazy);    		
			seg[id].lazy.init();//初始化
    	}
	 }
    li Info query(int id,int l,int r){
        if(inrange(seg[id].l,seg[id].r,l,r)){
            return seg[id].val;
        }else{
        	int mid=(seg[id].l+seg[id].r)>>1;
        	pushdown(id);
        	if(mid>=r){
        		return query(tl(id),l,r);
        	}else if(mid<l){
        		return query(tr(id),l,r);
        	}else{
				return (query(tl(id),l,mid)+query(tr(id),mid+1,r));
        	}
        }
    }
    li void modify(int id,int L,int R,int l,int r,Tag x){
        if(inrange(L,R,l,r)){
            maketag(id,x);
        }else if(!outofrange(L,R,l,r)){
            int mid=(L+R)>>1;
            pushdown(id);
            modify(tl(id),L,mid,l,r,x);
            modify(tr(id),mid+1,R,l,r,x);
            pushup(id);
        }
    }
}tr;
#define Tag SEG::Tag
#define Info SEG::Info
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>n>>p;
	PHI=phi(p);
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	tr.build(1,1,n);
	int q;
	cin>>q;
	for(int i=1;i<=q;i++){
		int op,l,r,k;
		cin>>op>>l>>r>>k;
		if(op==1){
			for(int i=0;i<p;i++){
				t[i]=(i+k)%p;
			}	
			Tag v(t);//赋值
			tr.modify(1,1,n,l,r,v);
		}else if(op==2){
			for(int i=0;i<p;i++){
				t[i]=(1ll*i*k)%p;
			}	
			Tag v(t);//赋值
			tr.modify(1,1,n,l,r,v);	
		}else if(op==3){
			for(int i=0;i<p;i++){
				t[i]=qmi(i,k,p)%p;
			}	
			Tag v(t);//赋值
			tr.modify(1,1,n,l,r,v);
		}else if(op==4){
			Info res=tr.query(1,l,r);
			ll ans=0;
			for(int i=0;i<p;i++){
				ans=(ans+qmi(i,k,p)*res.num[i]%p)%p;
			}	
			cout<<ans<<'\n';
		}else{
			Info res=tr.query(1,l,r);
			ll ans=1;
			for(int i=0;i<p;i++){
				ans=(ans*qmi(i,res.num[i],p))%p;
			}	
			cout<<ans<<'\n';
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值