zoukankan      html  css  js  c++  java
  • 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("
    ");
    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
    ",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("
    ");
    158 //      }
    159     }
    160     return 0;
    161 }
  • 相关阅读:
    【LCA倍增】POJ1330-Nearest Common Ancestors
    【AC自动机/fail树】BZOJ3172- [Tjoi2013]单词
    【费用流】BZOJ1221-[HNOI2001] 软件开发
    【KM】POJ2195/HDU1533-Going home
    【KM算法】HDU2255-奔小康赚大钱
    【匈牙利算法】BZOJ1059-[ZJOI2007]矩阵游戏
    【KMP】BZOJ3670-[Noi2014]动物园
    【Treap】BZOJ1588-[HNOI2002]营业额统计
    【Treap模板详细注释】BZOJ3224-普通平衡树
    【tarjan求割顶】BZOJ2730-[HNOI2012]矿场搭建
  • 原文地址:https://www.cnblogs.com/w-h-h/p/7714536.html
Copyright © 2011-2022 走看看