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

题链

SOL:

p与a不互质时,设c=b mod φ(p)(专门设出来是因为公式不能正常显示),如果b>=φ(p):a^ba^(c+φ(p))

(注意b<φ(p)的时候再减φ(p))

我们可以证明  φ(p) 在 log次迭代后到达1,以后的数就不会对答案产生贡献。

那么我们暴力计算每个数的logn次操作,我们再用链表维护要修改的点,树状数组维护前缀和,即可。

当然我们可以打c的x次幂的表,省掉一个log 

复杂度O(nlog^2)

#pragma comment(linker,"/stack:200000000")
#pragma GCC optimize("-Os")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
using namespace std;
#define sight(c) ('0'<=c&&c<='9')
#define gc nc
#define B 256
#define N 50007
#define LL long long
#define L(x) x&-x
int hea,head[N/B],n,op,pre[N],net[N],mo[N],p,m,c,l,r,ot,P[N],ptt;
LL AA[N];
inline char nc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
//int g[N][N/B];
int g[N],gg[N],tt[N];
int ff[B][10007],ggg[B][10007],ttt;
inline void read(int &x){
    static int b; static char c;
    for (b=1,c=gc();!sight(c);c=gc()) if (c=='-') b=-1;
    for (x=0;sight(c);c=gc())  x=x*10+c-48;
}
inline void read(LL &x){
    static int b; static char c;
    for (b=1,c=gc();!sight(c);c=gc()) if (c=='-') b=-1;
    for (x=0;sight(c);c=gc())  x=x*10+c-48;
}
inline int Mo(LL x,int mo){return x<mo?x:x%mo+mo;}
inline LL MO(LL x,LL mo) { x%=mo; if (x<0) x+=mo;return x;}
LL orz;
//inline int qsm(int x,int y,int& mo){
////   static int anw;
////   for (anw=1;y;y>>=1,x=((orz=(LL)x*x)<mo?orz:orz%mo+mo))
////    if (y&1) anw=((orz=(LL)anw*x)<mo?orz:orz%mo+mo);
////   return anw;    
//     return Mo()
//}
inline LL te(int x){static LL q;  for (q=0;x;x-=L(x)) q+=AA[x]; return q; }
inline void ask(int x,LL dla){for (;x<N;x+=L(x)) AA[x]+=dla;}
inline int fi(int x){
    static int ple,anw;
    ple=sqrt(x);  anw=1;
    for (int i=2;i<=ple;i++) if (x%i==0){
        anw*=i-1; x/=i;
        while (x%i==0) x/=i,anw=anw*i;
    } if (x>1) anw=anw*(x-1); 
    return anw;
}
void Pre(){
    for (int i=1;i<=n;i++) pre[i]=i-1,net[i]=i+1; 
    for (int i=n/B;~i;i--) head[i]=i*B; mo[0]=p; head[0]=1;
    for (int i=1;mo[i]=fi(mo[i-1]);i++) 
        if (mo[i-2]==1)  {
         ptt=i; break; }
    for (int i=ptt;~i;i--) {
        ff[i][0]=1; ggg[i][0]=1; 
        for (int g=1;g<10000;g++) ff[i][g]=Mo((LL)ff[i][g-1]*c,mo[i]);
        ttt=Mo((LL)ff[i][9999]*c,mo[i]);
        for (int g=1;g<10000;g++) ggg[i][g]=Mo((LL)ggg[i][g-1]*ttt,mo[i]);
    }
}
inline void doo(int x,int y){
    gg[x]=((tt[x]<mo[y])?tt[x]:tt[x]%mo[y]+mo[y]);
    //Mo(tt[x],mo[y]);
    for (int k=y;k;k--) gg[x]=//qs(gg[x],k-1);
     Mo((LL)ggg[k-1][gg[x]/10000]*ff[k-1][gg[x]%10000],mo[k-1]);
     gg[x]%=p;
}
void write(LL x){
   if (x<10) { putchar('0'+x);return; }write(x/10); putchar(x%10+'0');
}
inline void writeln(LL x){write(x); putchar('\n');}
signed main () {
     read(n); read(m); read(p); read(c);
     for (int i=1;i<=n;i++)  read(gg[i]),gg[i]%=p,tt[i]=gg[i],ask(i,gg[i]);
     Pre();
     while (m--) {
         read(op);
         if (op) { read(l);read(r); writeln(MO(te(r)-te(l-1),p)); } else{
           read(l); read(r);
           hea=head[l/B];
           while (hea< l) hea=net[hea];
           while (hea<=r) {
              ot=++P[hea]; g[hea]=gg[hea];
             doo(hea,ot);   ask(hea,gg[hea]-g[hea]); 
              if (ot>=ptt) {
                  for (int t=n/B;~t;t--) if (head[t]==hea) head[t]=net[hea];
                  net[pre[hea]]=net[hea]; pre[net[hea]]=pre[hea];
              }  
              hea=net[hea];
           }
        }
     } return 0;
}

 

posted @ 2018-02-24 17:31  泪寒之雪  阅读(238)  评论(0编辑  收藏  举报