题目链接

BZOJ4869

题解

这题调得我怀疑人生,,结果就是因为某些地方\(sb\)地忘了取模

前置题目:BZOJ3884

扩展欧拉定理:

\[c^a \equiv c^{a \mod \varphi(p) + [a \ge p]p} \pmod p
\]

我们发现当我们进行\(0\)操作,就相当于在\(a\)底部添加一层\(c\)

当我们进行得足够多的时候,\(\varphi(p)\)就会取到\(1\),从而不再变化

所以每个位置操作次数其实是有限的,为\(O(logp)\)次

为何是\(O(logp)\)次呢?

考虑欧拉函数:

\[\varphi(n) = n \prod\limits_{i = 1}^{k} \frac{p_i - 1}{p_i}
\]

由于质数一定是奇数,所以\(p_i - 1\)一定为偶数,所以操作一次后的\(p\)一定为偶数

偶数有\(2\)这个质因子,式子中就会存在\(\frac{1}{2}\)这一项,所以至少减少\(\frac{1}{2}\)

所以到达\(1\)是\(O(logp)\)的

用线段树进行维护

每次修改重新计算\(O(log^2p)\),总复杂度\(O(nlognlog^3p)\),凭信仰可过

由于每次快速幂底都是\(c\),我们可以预处理\(c^x\),从而做到\(O(nlognlog^2p)\)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
#define ls (u << 1)
#define rs (u << 1 | 1)
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int p[maxn],pi,isn[maxn];
void init(){
for (int i = 2; i <= 10000; i++){
if (!isn[i]) p[++pi] = i;
for (int j = 1; j <= pi && i * p[j] <= 10000; j++){
isn[i * p[j]] = true;
if (i % p[j] == 0) break;
}
}
}
int n,m,P[30],Pi,c,a[maxn],cnt[maxn],low[30];
LL C[30][maxn],CC[30][maxn];
int phi(int x){
int tmp = x,ans = x;
for (int i = 1; i <= pi && p[i] <= tmp; i++){
int v = p[i];
if (tmp % v == 0){
ans = ans / v * (v - 1);
while (tmp % v == 0) tmp /= v;
}
}
if (tmp - 1) ans = ans / tmp * (tmp - 1);
return ans;
}
LL qpow(int b,int md){
return CC[md][b / 10000] * C[md][b % 10000] % P[md];
}
int cal(int x,int t){
LL last,tmp = x;
if (tmp > P[t]) tmp = tmp % P[t] + P[t];
for(int i = t; i; i--)
{
last = tmp;
tmp = qpow(tmp,i - 1);
if (last >= low[i - 1]){
tmp += P[i - 1];
}
}
return tmp;
}
int sum[maxn << 2],val[maxn << 2];
void upd(int u){
sum[u] = (sum[ls] + sum[rs]) % P[0];
val[u] = val[ls] | val[rs];
}
void build(int u,int l,int r){
val[u] = 1;
if (l == r){sum[u] = a[l] % P[0]; return;}
int mid = l + r >> 1;
build(ls,l,mid);
build(rs,mid + 1,r);
upd(u);
}
void change(int u,int l,int r){
if (!val[u]) return;
if (l == r){
cnt[l]++;
if (cnt[l] >= Pi) val[u] = 0;
sum[u] = cal(a[l],cnt[l]) % P[0];
return;
}
int mid = l + r >> 1;
change(ls,l,mid);
change(rs,mid + 1,r);
upd(u);
}
void modify(int u,int l,int r,int L,int R){
if (!val[u]) return;
if (l >= L && r <= R){
change(u,l,r);
return;
}
int mid = l + r >> 1;
if (mid >= L) modify(ls,l,mid,L,R);
if (mid < R) modify(rs,mid + 1,r,L,R);
upd(u);
}
int query(int u,int l,int r,int L,int R){
if (l >= L && r <= R) return sum[u] % P[0];
int mid = l + r >> 1;
if (mid >= R) return query(ls,l,mid,L,R);
if (mid < L) return query(rs,mid + 1,r,L,R);
return (query(ls,l,mid,L,R) + query(rs,mid + 1,r,L,R)) % P[0];
}
int main(){
init();
n = read(); m = read(); P[0] = read(); c = read();
REP(i,n) a[i] = read();
while (P[Pi] != 1){
++Pi;
P[Pi] = phi(P[Pi - 1]);
}
P[++Pi] = 1;
for (register int t = 0; t <= Pi; t++){
C[t][0] = CC[t][0] = 1 % P[t];
low[t] = 0;
for (register int i = 1; i <= 10000; i++){
C[t][i] = C[t][i - 1] * c;
if (C[t][i] >= P[t] && !low[t]) low[t] = i;
C[t][i] %= P[t];
}
CC[t][1] = C[t][10000];
for (register int i = 2; i <= 10000; i++)
CC[t][i] = CC[t][i - 1] * C[t][10000] % P[t];
}
build(1,1,n);
int opt,l,r;
while (m--){
opt = read(); l = read(); r = read();
if (!opt) modify(1,1,n,l,r);
else printf("%d\n",query(1,1,n,l,r));
}
return 0;
}

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

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

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

  2. 【bzoj4869】[Shoi2017]相逢是问候 扩展欧拉定理+并查集+树状数组

    题目描述 Informatik verbindet dich und mich. 信息将你我连结. B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以分为两种:0 ...

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

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

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

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

  5. Bzoj4869: [Shoi2017]相逢是问候

    题面 传送门 Sol 摆定理 \[ a^b\equiv \begin{cases} a^{b\%\phi(p)}~~~~~~~~~~~gcd(a,p)=1\\ a^b~~~~~~~~~~~~~~~~~ ...

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

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

  7. BZOJ:4869: [Shoi2017]相逢是问候

    4869: [Shoi2017]相逢是问候 先说点正经的…… 显然做了有限次(我只知道是有限次,而且不会大,别人说是log次?)修改以后会达到不动点,即以后怎么修改都不变了. 然后就随便做了.(3个l ...

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

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

  9. 【BZOJ4869】相逢是问候 [线段树][欧拉定理]

    相逢是问候 Time Limit: 40 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description Informatikverbin ...

随机推荐

  1. Source Insight的使用

    1. source insight查看函数的上一级调用的位置(函数) --> 鼠标放在函数上,右键 选择 Jump To caller,就可以看到有哪些函数调用它了:

  2. python 装饰器 回顾 及练习

    # 复习 # 讲作业 # 装饰器的进阶 # functools.wraps # 带参数的装饰器 # 多个装饰器装饰同一个函数 # 周末的作业 # 文件操作 # 字符串处理 # 输入输出 # 流程控制 ...

  3. ruby OpenURI模块使用

    OpenURI is an easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP(OpenURI支持重定向) 像打开普通文件那样打开ht ...

  4. Java学习笔记八:Java的流程控制语句之循环语句

    Java的流程控制语句之循环语句 一:Java循环语句之while: 生活中,有些时候为了完成任务,需要重复的进行某些动作.如参加 10000 米长跑,需要绕 400 米的赛道反复的跑 25 圈.在 ...

  5. Python字符串处理:过滤字符串中的英文与符号,保留汉字

    使用Python 的re模块,re模块提供了re.sub用于替换字符串中的匹配项. re.sub(pattern, repl, string, count=0) 参数说明: pattern:正则重的模 ...

  6. redis入门:介绍、特点、安装、各类型常用操作

    一.redis介绍 Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件. Redis支持多种类型的数据结构,如 字符串(strings), 散列(ha ...

  7. BeyondCompare3 提示许可证密钥已被撤销解决方法

    今天对比文件提示 许可证密钥已被撤销:3281-0350! 找过了几个注册码还是不行. 正确简单的解决方法: 1.找到 BCState.xml 文件 ​ 2.编辑器打开,删除<TCheckFor ...

  8. Python 3基础教程32-正则

    本文介绍Python的正则,通过本文介绍和一个练习,对正则有一个基本了解就可以. # 正则表达式 ''' 正则表达式是有一些特殊字符组成,能够帮你找到一些符合一定规则的字符串 先来了解几个符号所代表的 ...

  9. Python 3基础教程29-os模块

    本文介绍os模块,主要是介绍一些文件的相关操作. 你还有其他方法去查看os 1. help() 然后输入os 2. Python接口文档,前面提到的用浏览器打开的,os文件路径为:C:\Users\A ...

  10. mysql数据库----Pymysql

    本节重点: pymysql下载和使用 sql注入 增.删.改:conn.commit() 查:fetchone.fetchmany.fetchall 一.pymysql的下载和使用 之前我们都是通过M ...