http://www.lydsy.com/JudgeOnline/problem.php?id=4869

题面复制于洛谷:https://www.luogu.org/problemnew/show/P3747#sub

参考洛谷的前两篇(也是仅有的两篇)题解。

首先我们要知道一个公式:

这又被叫做扩展欧拉定理,证明我们并不关心。

有了扩展欧拉定理,我们就能够避免高精度从而求出对于任意一个数的0操作之后变成什么数了。

(递归或者迭代选一个,递归好理解,迭代有助于理解下面的题解,而且常数小)

我们又有一个结论,对于一个p,它无限递归p=phi(p)直到p=1为止的深度为O(logp)。

这样的好处在于我们虽然修改了很多次,但是当修改次数大于logp的时候,此时你再怎么修改也没有用了因为你的指数为1相当于没有操作。

那么显然对于1我们记录该元素被操作了几次,然后暴力修改即可,可用线段树维护。复杂度O(nlognlogp)。(请注意这个复杂度是假的)

这样的复杂度我们交到bzoj上是没有问题的,但是交到洛谷上会TLE3个点。将递归改成迭代,预处理每个p的phi,各种常数优化也会TLE2个点。

emmm……why?

当然是因为我们的复杂度没算对啊。

对于单点修改,显然每次修改是O(logplogp)……等等,怎么多出来一个O(logp)。

忘了我们使用了快速幂了吗,我们多出来的O(logp)就是这么来的。

考虑除掉这个O(logp),显然预处理快速幂。

如果你写的是迭代的话,你就会发现底数永远都是c不变,变的只是指数和模数, 且指数最大是p=1e8。

我们可以先求出不同模数且指数<=1e5的c的幂,我们还可以求不同模数且指数=整1e5的c的幂。

这就很像分块了,显然当我们要求指数为k时,k=x*1e5+y(y<1e5)显然可求。

这样我们预处理出所有的数在多少次操作后的值,则我们的复杂度就是O(nlognlogp)。

吐槽:最开始学完扩欧之后觉得这题洛谷给的难度高了,怎么就NOI+了,后来在TLE之后一看woc还有这种操作……

神题神题……

(然而博主并不想写正解,放的代码只能过bzoj,正解如果有时间的话会补上的emmm)

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<map>
using namespace std;
typedef long long ll;
const int N=5e4+;
const int O=1e4+;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct tree{
ll v,t;
}tr[N*];
int su[O],he[O],cnt,phi[],n,m;
ll p,c,logp,b[N];
bool ok;
inline ll qpow(ll k,int p){
ll ans=,s=c;
while(k){
if(k&)ans=ans*s;
s*=s;k>>=;
if(s>=p)ok=,s%=p;
if(ans>=p)ok=,ans%=p;
}
return ans;
}
int Euler(int k){
int res=k;
for(int i=;su[i]*su[i]<=k;i++){
if(k%su[i]==){
res-=res/su[i];
while(k%su[i]==)k/=su[i];
}
}
if(k>)res-=res/k;
return res;
}
void prime(){
for(int i=;i<O;i++){
if(he[i]==){
cnt++;
su[cnt]=i;
}
for(int j=;j<=cnt&&i*su[j]<O;j++){
he[su[j]*i]=;
if(i%su[j]==)break;
}
}
phi[logp]=p;
while(phi[logp]!=)phi[++logp]=Euler(phi[logp-]);
phi[++logp]=;
}
void build(int a,int l,int r){
if(l==r){
tr[a].v=b[l]%p;
return;
}
int mid=(l+r)>>;
build(a<<,l,mid);build(a<<|,mid+,r);
tr[a].v=(tr[a<<].v+tr[a<<|].v)%p;
}
ll suan(ll v,ll k){
ll tmp=v;
if(tmp>phi[k])tmp=tmp%phi[k]+phi[k];
for(int i=k;i>;i--){
ok=;tmp=qpow(tmp,phi[i-]);
if(ok)tmp+=phi[i-];
}
return tmp;
}
void gai(int a,int l,int r,int l1,int r1){
if(tr[a].t>=logp)return;
if(r<l1||r1<l)return;
if(l==r){
tr[a].t++;
tr[a].v=suan(b[l],tr[a].t);
return;
}
int mid=(l+r)>>;
gai(a<<,l,mid,l1,r1);gai(a<<|,mid+,r,l1,r1);
tr[a].v=(tr[a<<].v+tr[a<<|].v)%p;
tr[a].t=min(tr[a<<].t,tr[a<<|].t);
}
ll wen(int a,int l,int r,int l1,int r1){
if(r<l1||r1<l)return ;
if(l1<=l&&r<=r1)return tr[a].v;
int mid=(l+r)>>;
return (wen(a<<,l,mid,l1,r1)+wen(a<<|,mid+,r,l1,r1))%p;
}
int main(){
n=read(),m=read(),p=read(),c=read();
prime();
for(int i=;i<=n;i++)b[i]=read();
build(,,n);
for(int i=;i<=m;i++){
int op=read(),l=read(),r=read();
if(!op)gai(,,n,l,r);
else printf("%lld\n",wen(,,n,l,r));
}
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

BZOJ4869:[SHOI2017]相逢是问候——题解的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 关于 NPOI 导出的 Excel 出现“部分内容有问题” 的解决方法

    近期发现使用 NPOI 导出的 Excel 文件,有部分用户反映在打开时报错,测试了一下,发现在低版本的 Office 中(2003版,配合2007格式兼容包)打开正常,但在高版本 Office 中, ...

  2. hdu2099整除的尾数(暴力 省赛)

    整除的尾数 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  3. Linux命令应用大词典-第22章 GRUB

    22.1 grub-md5-crypt:使用MD5格式加密口令 22.2 grub-install:在设备上安装GRUB 22.3 grub:进入GRUB命令shell 22.4 grub-crypt ...

  4. 【转】APP推广什么是cpa,cps,cpm

    转载自:http://www.apptg.cn 经常做做APP推广和做运营的同学对于cpa,cps,cpm,cpc这些名词肯定不会陌生,也基本都知道其表示的含义,但是对于新手来说,这几个词的含义还是不 ...

  5. Visual Studio Code——PHP Debug扩展

    最近在使用PHP开发,使用了很多IDE,发现都不是很顺手,之前一直都在使用Sublime Text,但是作为一个爱折腾的人,当我发现VS Code以后觉得很是很适合自己的编程需要的.配置过程中遇到了一 ...

  6. 某即时通信工具与RMS结合

    某客户内部使用及时通信工具与RMS相结合,如果客户使用了海外版Office 365E3可以直接在手机端使用Office app打开. 如果客户没有使用海外版Office 365E3的版本,需要结合本地 ...

  7. Machine Learning笔记整理 ------ (四)线性模型

    1. 线性模型 基本形式:给定由d个属性描述的样本 x = (x1; x2; ......; xd),其中,xi是x在第i个属性上的取值,则有: f(x) = w1x1 + w2x2 + ...... ...

  8. matlab 常用集合相关的函数

    Matlab常用的集合相关的函数如下:     union(A,B)              %求集合A和集合B的并集     intersect(A,B)             %求集合A和集合 ...

  9. HADOOP docker(十):hdfs 结构体系

    1.简介2.namenode和datanode3.The File System Namespace 文件系统命名空间4.Data Replication 数据复制5.Replica Placemen ...

  10. DFS中的奇偶剪枝(技巧)

    剪枝是什么,简单的说就是把不可行的一些情况剪掉,例如走迷宫时运用回溯法,遇到死胡同时回溯,造成程序运行时间长.剪枝的概念,其实就跟走迷宫避开死胡同差不多.若我们把搜索的过程看成是对一棵树的遍历,那么剪 ...