• 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 

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

    正解:扩展欧拉定理+线段树。

    扩展欧拉定理:$a^{b} mod p=a^{b mod varphi(p)+varphi(p)}$,如果$b<varphi(p)$则不加$varphi(p)$。

    因为一个数取$log$次$varphi$就会变成$1$,于是我们可以发现,一个数变换$log$次以后就不会变了。

    于是用线段树记录每个数变换的次数,每次单点修改时直接用$varphi$从后往前递推。

    因为每次要快速幂,所以复杂度是$O(nlog^{3}n)$的,我们预处理$c^{x}$和$c^{20000x}$就能$O(1)$算出幂了。

     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 #define ls (x<<1)
     6 #define rs (x<<1|1)
     7 #define N (100005)
     8 
     9 using namespace std;
    10 
    11 int sum[N<<2],tag[N<<2],a[N],phi[105],qp[105][20005],qw[105][20005],n,m,c,tot,base=20000;
    12 
    13 il int gi(){
    14   RG int x=0,q=1; RG char ch=getchar();
    15   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    16   if (ch=='-') q=-1,ch=getchar();
    17   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    18   return q*x;
    19 }
    20 
    21 il int mul(RG int a,RG int b,RG int rhl){
    22   return 1LL*a*b>=rhl ? 1LL*a*b%rhl+rhl : a*b;
    23 }
    24 
    25 il int get_phi(RG int x){
    26   RG int res=x;
    27   for (RG int i=2;i*i<=x;++i){
    28     if (x%i) continue;
    29     while (!(x%i)) x/=i;
    30     res=res/i*(i-1);
    31   }
    32   if (x!=1) res=res/x*(x-1); return res;
    33 }
    34 
    35 il void pre(){
    36   while (phi[tot]!=1) ++tot,phi[tot]=get_phi(phi[tot-1]); phi[++tot]=1;
    37   for (RG int i=0;i<=tot;++i){
    38     qp[i][0]=qw[i][0]=mul(1,1,phi[i]);
    39     for (RG int j=1;j<=base;++j)
    40       qp[i][j]=mul(qp[i][j-1],c,phi[i]);
    41     for (RG int j=1;j<=base;++j)
    42       qw[i][j]=mul(qw[i][j-1],qp[i][base],phi[i]);
    43   }
    44   return;
    45 }
    46 
    47 il int trans(RG int x,RG int k){
    48   while (k) --k,x=mul(qw[k][x/base],qp[k][x%base],phi[k]);
    49   return x>=phi[0] ? x-phi[0] : x;
    50 }
    51 
    52 il void pushup(RG int x){
    53   sum[x]=sum[ls]+sum[rs]; if (sum[x]>=phi[0]) sum[x]-=phi[0];
    54   tag[x]=min(tag[ls],tag[rs]); return;
    55 }
    56 
    57 il void build(RG int x,RG int l,RG int r){
    58   if (l==r){ sum[x]=(a[l]=gi())%phi[0]; return; } RG int mid=(l+r)>>1;
    59   build(ls,l,mid),build(rs,mid+1,r),pushup(x); return;
    60 }
    61 
    62 il void update(RG int x,RG int l,RG int r,RG int xl,RG int xr){
    63   if (tag[x]>=tot) return;
    64   if (l==r){ ++tag[x],sum[x]=trans(a[l],tag[x]); return; }
    65   RG int mid=(l+r)>>1;
    66   if (xr<=mid) update(ls,l,mid,xl,xr);
    67   else if (xl>mid) update(rs,mid+1,r,xl,xr);
    68   else update(ls,l,mid,xl,mid),update(rs,mid+1,r,mid+1,xr);
    69   pushup(x); return;
    70 }
    71 
    72 il int query(RG int x,RG int l,RG int r,RG int xl,RG int xr){
    73   if (xl<=l && r<=xr) return sum[x]; RG int mid=(l+r)>>1;
    74   if (xr<=mid) return query(ls,l,mid,xl,xr);
    75   if (xl>mid) return query(rs,mid+1,r,xl,xr);
    76   RG int res=query(ls,l,mid,xl,mid);
    77   res+=query(rs,mid+1,r,mid+1,xr);
    78   if (res>=phi[0]) res-=phi[0]; return res;
    79 }
    80 
    81 int main(){
    82 #ifndef ONLINE_JUDGE
    83   freopen("meet.in","r",stdin);
    84   freopen("meet.out","w",stdout);
    85 #endif
    86   n=gi(),m=gi(),phi[0]=gi(),c=gi(),pre(),build(1,1,n);
    87   while (m--){
    88     RG int op=gi(),l=gi(),r=gi();
    89     if (op) printf("%d
    ",query(1,1,n,l,r)%phi[0]);
    90     else update(1,1,n,l,r);
    91   }
    92   return 0;
    93 }
  • 相关阅读:
    阶段2 JavaWeb+黑马旅游网_15-Maven基础_第3节 maven标准目录结构和常用命令_07maven常用命令
    阶段2 JavaWeb+黑马旅游网_15-Maven基础_第3节 maven标准目录结构和常用命令_06maven标准目录结构
    阶段2 JavaWeb+黑马旅游网_15-Maven基础_第2节 maven的安装和仓库种类_05仓库的种类和彼此关系
    阶段2 JavaWeb+黑马旅游网_15-Maven基础_第2节 maven的安装和仓库种类_04maven的安装
    阶段2 JavaWeb+黑马旅游网_15-Maven基础_第1节 基本概念_03maven一键构建概念
    阶段2 JavaWeb+黑马旅游网_15-Maven基础_第1节 基本概念_02maven依赖管理的概念
    kmalloc、vmalloc、__get_free_pages()的区别
    如何增加内核模块
    VFS四大对象之四-struct file
    VFS四大对象之三 struct dentry
  • 原文地址:https://www.cnblogs.com/wfj2048/p/8111698.html
Copyright © 2020-2023  润新知