相逢是问候

Time Limit: 40 Sec  Memory Limit: 512 MB
[Submit][Status][Discuss]

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。

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

  1 ≤ n ≤ 50000, 1 ≤ m ≤ 50000, 1 ≤ p ≤ 100000000, 0 < c <p, 0 ≤ ai < p

Solution

  首先,我们运用欧拉定理:

  然后还有一个定理:一个数在执行log次操作后,值不会改变。

  于是乎,我们可以运用线段树,暴力修改每一个值,如果值都不变了则不修改。

  然后我们再考虑一下,怎么修改这个值:
  已知a(原值)times(修改次数),我们考虑每一次%什么,
    考虑每一次b的模数。
    首先如果b%phi(p),意味着a^b%p下同余。
    如果这一次b%phi(phi(p)),意味着a^bphi(p)下同余,
    同时也意味着下一次在%phi(p)意义下。
    我们要让答案最后是在%p意义下的,那么显然每次b%phi[times-1]
  再带上快速幂,那么这样效率就是O(nlog^3(n))的。

Code

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long s64; const int ONE = ;
const int INF = ; int n,m,p,C;
int opt,x,y;
int a[ONE],phi[ONE],p_num;
int MOD;
int res; struct power
{
int value;
int cnt;
}Node[ONE]; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} int Getphi(int n)
{
int res = n;
for(int i=; i*i<=n; i++)
if(n % i == )
{
res = res/i*(i-);
while(n % i == ) n /= i;
}
if(n != ) res = res/n*(n-);
return res;
} int Quickpow(int a,int b,int MOD)
{
int res = ;
while(b)
{
if(b & ) res = (s64)res * a % MOD;
a = (s64)a * a % MOD;
b >>= ;
}
return res;
} void Build(int i,int l,int r)
{
if(l == r)
{
Node[i].value = a[l] % MOD;
return;
}
int mid = l+r>>;
Build(i<<, l, mid);
Build(i<<|, mid + , r);
Node[i].value = (Node[i<<].value + Node[i<<|].value) % MOD;
} int Calc(int a, int times)
{
for(int i=times; i>=; i--)
{
if(a >= phi[i]) a = a%phi[i] + phi[i];
a = Quickpow(C, a, phi[i-]);
if(!a) a = phi[i-];
}
return a;
} void Update(int i,int l,int r,int L,int R)
{
if(Node[i].cnt >= p_num) return;
if(l == r)
{
Node[i].value = Calc(a[l], ++Node[i].cnt);
return;
} int mid = l+r>>;
if(L <= mid) Update(i<<, l, mid, L, R);
if(mid+ <= R) Update(i<<|, mid+, r, L, R); Node[i].value = (Node[i<<].value + Node[i<<|].value) % MOD;
Node[i].cnt = min(Node[i<<].cnt, Node[i<<|].cnt);
} void Query(int i,int l,int r,int L,int R)
{
if(L<=l && r<=R)
{
res = (res + Node[i].value) % MOD;
return;
} int mid = l+r>>;
if(L <= mid) Query(i<<, l, mid, L, R);
if(mid+ <= R) Query(i<<|, mid+, r, L, R);
} int main()
{
n = get(); m = get(); p = get(); C = get();
for(int i=; i<=n; i++) a[i] = get(); MOD = phi[] = p;
while(p!=) phi[++p_num] = p = Getphi(p);
phi[++p_num] = ;
Build(, , n); while(m--)
{
opt = get();
x = get(); y = get();
if(!opt) Update(, , n, x, y);
else
{
res = ;
Query(, , n, x, y);
printf("%d\n", res);
}
}
}

【BZOJ4869】相逢是问候 [线段树][欧拉定理]的更多相关文章

  1. [BZOJ4869][六省联考2017]相逢是问候(线段树+扩展欧拉定理)

    4869: [Shoi2017]相逢是问候 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1313  Solved: 471[Submit][Stat ...

  2. 【bzoj4869】[Shoi2017]相逢是问候 线段树+扩展欧拉定理

    Description Informatikverbindetdichundmich. 信息将你我连结.B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以 分为两 ...

  3. BZOJ4869 [Shoi2017]相逢是问候 【扩展欧拉定理 + 线段树】

    题目链接 BZOJ4869 题解 这题调得我怀疑人生,,结果就是因为某些地方\(sb\)地忘了取模 前置题目:BZOJ3884 扩展欧拉定理: \[c^a \equiv c^{a \mod \varp ...

  4. SHOI 2017 相逢是问候(扩展欧拉定理+线段树)

    题意 https://loj.ac/problem/2142 思路 一个数如果要作为指数,那么它不能直接对模数取模,这是常识: 诸如 \(c^{c^{c^{c..}}}\) 的函数递增飞快,不是高精度 ...

  5. 洛谷P3747 [六省联考2017]相逢是问候

    传送门 题解 扩展欧拉定理. 线段树维护,已经全改到底了的节点就不管,不然暴力修改下去. //Achen #include<algorithm> #include<iostream& ...

  6. 【BZOJ4869】相逢是问候(线段树,欧拉定理)

    [BZOJ4869]相逢是问候(线段树,欧拉定理) 题面 BZOJ 题解 根据欧拉定理递归计算(类似上帝与集合的正确用法) 所以我们可以用线段树维护区间最少的被更新的多少次 如果超过了\(\varph ...

  7. bzoj 4869: [Shoi2017]相逢是问候 [扩展欧拉定理 线段树]

    4869: [Shoi2017]相逢是问候 题意:一个序列,支持区间\(a_i \leftarrow c^{a_i}\),区间求和.在模p意义下. 类似于开根操作,每次取phi在log次后就不变了. ...

  8. BZOJ4869 六省联考2017相逢是问候(线段树+欧拉函数)

    由扩展欧拉定理,a^(a^(a^(……^x)))%p中x作为指数的模数应该是φ(φ(φ(φ(……p)))),而p取log次φ就会变为1,也即每个位置一旦被修改一定次数后就会变为定值.线段树维护区间剩余 ...

  9. bzoj4869: [Shoi2017]相逢是问候(欧拉函数+线段树)

    这题是六省联考的...据说数据还出了点锅,心疼六省选手QAQ 首先要知道扩展欧拉定理... 可以发现每次区间操作都会使模数进行一次phi操作,而一个数最多取logp次phi就会变成1,这时后面的指数就 ...

随机推荐

  1. c# load xml 中文报错

    <?xml version="1.0" encoding="GB2312"?>

  2. Android 网络编程 API笔记 - java.net 包 权限 地址 套接字 相关类 简介

    Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...

  3. lintcode-171-乱序字符串

    171-乱序字符串 给出一个字符串数组S,找到其中所有的乱序字符串(Anagram).如果一个字符串是乱序字符串,那么他存在一个字母集合相同,但顺序不同的字符串也在S中. 注意事项 所有的字符串都只包 ...

  4. TCP系列04—连接管理—3、TCP连接的半打开和半关闭

    在前面部分我们我们分别介绍了三次握手.四次挥手.同时打开和同时关闭,TCP连接还有两种场景分别是半打开(Half-Open)连接和半关闭(Half-Close)连接.TCP是一个全双工(Full-Du ...

  5. Jmeter系列-webdriver插件

    1.下载地址    JMeterPlugins-WebDriver-1.1.2 2.将JMeterPlugins-WebDriver-1.1.2\lib\ext中的*.jar拷贝到D:\apache- ...

  6. Perfmon - 脚本自动监控

    PerfMon-Windows性能监视器是个好东西,可以辅助我们分析发生问题时间段服务器资源占用情况,但是部署性能计数器确实一个相当麻烦的事情,往往这种枯燥的事别人还做不了,只能由我们这些希望获取到P ...

  7. SpringBoot2.0(三) 文件上传

    SpringBoot中发起文件上传示例: /** * 文件上传 * @param multipartFile * @param path * @return */ @RequestMapping(va ...

  8. JavaScript 语句标识符,变量周期,常见的HTML事件

    语句 描述 break 用于跳出循环. catch 语句块,在 try 语句块执行出错时执行 catch 语句块. continue 跳过循环中的一个迭代. do ... while 执行一个语句块, ...

  9. vs2015常用代码块与自定义代码块

    常用代码块 代码段名 描    述 #if 该代码段用#if和#endif命令围绕代码 #region 该代码段用#region和#endregion命令围绕代码 ~ 该代码段插入一个析构函数 att ...

  10. 利用FluidMoveBehavior制作出手机通讯录平滑的效果

    最近学习Blend,原来Blend制作动画等效果非常棒.下面演示一下FluidMoveBehavior应用,利用Blend中行为中的FluidMoveBehavior制作出手机通讯录平滑的效果 1.在 ...