https://codeforces.com/gym/102875/problem/A
p<=30
可以建立30颗线段树维护
然后看操作
一.add 懒标记
二.mul
三.mi 好像不能找到
于是懒标记貌似不能做,
但是考虑结果都要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;
}