BZOJ4869: [Shoi2017]相逢是问候

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

 

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


根据欧拉定理,当更新超过一定次数时,phi(p)等于1,不会再改变了,
于是线段树暴力更新,统计节点更新次数,当更新次数大于变成phi(1)=1的个数就不再管它了
  1 **************************************************************
  2     Problem: 4869
  3     User: white_hat_hacker
  4     Language: C++
  5     Result: Accepted
  6     Time:24092 ms
  7     Memory:2776 kb
  8 ****************************************************************/
  9  
 10 #include<cstdio>
 11 #include<cstdlib>
 12 #include<algorithm>
 13 #include<cstring>
 14 #include<vector>
 15 #define MAXN 50005
 16 #define DEBUG 0
 17 #define ll long long
 18 using namespace std;
 19 int dat[MAXN*4];
 20 int cnt[MAXN*4];
 21 int a[MAXN];
 22 int n,c;
 23 int MOD,tot;
 24 int phi[MAXN];
 25 int Phi(int x){
 26     int ret=x;
 27     for(int i=2;i*i<=x;i++){
 28         if(!(x%i)){
 29             ret/=i;ret*=(i-1);
 30             while(!(x%i)){
 31                 x/=i;
 32             }
 33         }
 34     }
 35     if(x^1){
 36         ret/=x; ret*=(x-1);
 37     }
 38     return ret;
 39 }
 40 void work(int x){
 41     phi[tot]=x;
 42     tot++;
 43     if(1==x){
 44         return ;
 45     }
 46     work(Phi(x));
 47 }
 48 int read(){
 49     int x=0;char ch=getchar();
 50     while(ch<'0'||ch>'9'){ch=getchar();}
 51     while(ch>='0'&&c<='9'){x=x*10+ch-'0';ch=getchar();}
 52     return x;
 53 }
 54 int Power(int a,int b,int p){
 55     int ret=1;
 56     while(b){
 57         if(b&1){
 58             ret=ret*a%p;
 59         }
 60         a=a*a%p;
 61         b>>=1;
 62     }
 63     return ret;
 64 }
 65 int Pow(int a,int b,int p,bool &bi){
 66     int ret=1;
 67     bool fx=0;
 68     while(b){
 69         if(b&1){
 70             bi|=(fx|(1LL*ret*a>=p));
 71             ret=1LL*ret*a%p;
 72         }
 73         fx|=(1LL*a*a>=p);
 74         a=1LL*a*a%p;
 75         b>>=1;
 76     }
 77     return ret;
 78 }
 79 int solve(int a,int L){
 80     int ret=a%phi[L];
 81     bool bi=(a>=phi[L]);
 82     for(int i=L;i>=1;i--){
 83         ret=Pow(c,ret+((bi==true)?phi[i]:0),phi[i-1],bi);
 84     }
 85     return ret;
 86 }
 87 void change(int a,int b,int k,int L,int R){
 88     if(cnt[k]>=tot-1){
 89         return ;
 90     }
 91     if(b<=L||R<=a){
 92         return ;
 93     }
 94     if(L+1==R){
 95         cnt[k]++;
 96         dat[k]=solve(::a[L],cnt[k]);
 97         return ;
 98     }
 99     change(a,b,k<<1,L,(L+R)>>1);
100     change(a,b,k<<1|1,(L+R)>>1,R);
101     dat[k]=(dat[k<<1]+dat[k<<1|1])%MOD;
102     cnt[k]=min(cnt[k<<1],cnt[k<<1|1]);
103 }
104 int query(int a,int b,int k,int L,int R){
105     if(b<=L||R<=a){
106         return 0;
107     }
108     else if(a<=L&&R<=b){
109         return dat[k];
110     }
111     else{
112         int lc=query(a,b,k<<1,L,(L+R)>>1);
113         int rc=query(a,b,k<<1|1,(L+R)>>1,R);
114         return (lc+rc)%MOD;
115     }
116 }
117 void build(int k,int L,int R){
118     if(L+1==R){
119         dat[k]=a[L];
120         return ;
121     }
122     build(k<<1,L,(L+R)>>1);
123     build(k<<1|1,(L+R)>>1,R);
124     dat[k]=(dat[k<<1]+dat[k<<1|1])%MOD;
125 }
126 int main()
127 {
128     //freopen("data.in","r",stdin);
129     //freopen("my.out","w",stdout);
130     int T;
131     scanf("%d%d%d%d",&n,&T,&MOD,&c);
132     work(MOD);
133     phi[tot++]=1;
134     for(int i=1;i<=n;i++){
135         scanf("%d",&a[i]);
136     }
137     build(1,1,n+1);
138 //      if(DEBUG){
139 //          for(int i=1;i<=n;i++){
140 //              printf("%d ",query(i,i+1,1,1,n+1));
141 //          }
142 //          printf("\n");
143 //      }
144     for(int i=1;i<=T;i++){
145         int p,L,R;
146         scanf("%d%d%d",&p,&L,&R);
147         if(!p){
148             change(L,R+1,1,1,n+1);
149         }
150         else{
151             printf("%d\n",query(L,R+1,1,1,n+1));
152         }
153 //      if(DEBUG){
154 //          for(int i=1;i<=n;i++){
155 //              printf("%d ",query(i,i+1,1,1,n+1));
156 //          }
157 //          printf("\n");
158 //      }
159     }
160     return 0;
161 }

 

posted @ 2017-10-23 09:22  white_hat_hacker  阅读(167)  评论(0编辑  收藏  举报