[BZOJ 4809] 相逢是问候
Link:
Solution:
以前没见过的套路题……
1、使用EXT欧拉定理降幂的套路:
$a^{x}=a^{xmod\phi(P)+\phi(P)} mod P$,且$x\ge P$
这样对于$c^{c^{c^x}}modP$就能递推/递归得套用上述定理计算,每层模数多套一层$\phi$即可
注意每次在快速幂时要判断当前指数是否大于当前模数才能用EXT!
2、能证明一个数最多求$log$次$\phi$就会变成1
这样在$log$次内暴力更新,否则不管,就能保证$O(n*log^3)$
3、复杂度中的3个$log$分别是:
更新$log$次,每次更新迭代$log$层,每层要算一次快速幂
明显只能优化快速幂。由于底不变,模数只有$log$种,想到分数的前后两部分预处理!
分块预处理出$[1,(1<<16)]$和$[1*(1<<16),(1<<16)*(1<<16)]$的答案以及与模数的大小关系
这样每次拆出指数的前16位和后16位$O(1)$计算答案和大小关系就能做到$O(n*log^2)$
4、听说原题数据锅了……
虽然$\phi(2)$和$\phi(1)$都为1,但要更新到$\phi(1)$!
否则在最顶层指数为0时最终会迭代出$cmod2$而非$cmod1$,不一定为0!
Code:
#include <bits/stdc++.h> using namespace std;
#define X first
#define Y second
#define pb push_back
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=1e5+;
ll pre[][<<][];
bool f[][<<][];
int n,m,p,c,dat[MAXN],phi[],cnt; int getphi(int x)
{
int ret=x;
for(int i=;i*i<=x;i++)
if(x%i==)
{
ret=ret/i*(i-);
while(x%i==) x/=i;
}
if(x!=) ret=ret/x*(x-);
return ret;
}
ll quick_pow(ll a,ll b,ll MOD,bool &f)
{
ll ret=;
for(;b;b>>=,a=a*a%MOD)
{
//判断是否大于某个数两个地方都要判!
if(b&) f|=(ret*a>=MOD),ret=ret*a%MOD;
f|=(a*a>=MOD&&b!=);
}
return ret;
}
int QP(int x,int num,bool &flag)
{
int a=x&((<<)-),b=x>>;
ll ret=1ll*pre[num][a][]*pre[num][b][];
flag=f[num][a][]|f[num][b][]|(ret>=phi[num]);
return ret%phi[num];
}
int cal(int x,int st)
{
int ret=x;
if(ret>=phi[st])
ret=ret%phi[st]+phi[st];
while(st--)
{
bool f=;
ret=QP(ret,st,f);
//注意特判,仅在指数>模数时可使用EXT欧拉定理
if(f&&st) ret+=phi[st];
}
return ret%p;
}
void PRE()
{
//分块预处理
for(int i=;i<=cnt;i++)
{
pre[i][][]=pre[i][][]=;
if(phi[i]==) f[i][][]=f[i][][]=;
pre[i][][]=quick_pow(c,,phi[i],f[i][][]);
int tmp=pre[i][][]=quick_pow(c,<<,phi[i],f[i][][]); for(int j=;j<<<;j++)
{
f[i][j][]=f[i][j-][]|(pre[i][j-][]*c>=phi[i]);
pre[i][j][]=pre[i][j-][]*c%phi[i];
f[i][j][]=f[i][j-][]|(pre[i][j-][]*tmp>=phi[i]);
pre[i][j][]=pre[i][j-][]*tmp%phi[i];
}
}
} namespace SegmentTree
{
#define mid ((l+r)>>1)
#define ls k<<1
#define rs k<<1|1
#define lc ls,l,mid
#define rc rs,mid+1,r int sum[MAXN<<],tag[MAXN<<];
void pushup(int k)
{
tag[k]=min(tag[ls],tag[rs]);
sum[k]=(sum[ls]+sum[rs])%p;
}
void build(int k,int l,int r)
{
if(l==r)
{sum[k]=dat[l]%p;tag[k]=;return;}
build(lc);build(rc);pushup(k);
}
void modify(int a,int b,int k,int l,int r)
{
if(tag[k]>=cnt) return;
if(l==r)
{sum[k]=cal(dat[l],++tag[k]);return;}
if(a<=mid) modify(a,b,lc);
if(b>mid) modify(a,b,rc);
pushup(k);
}
int query(int a,int b,int k,int l,int r)
{
if(a<=l&&r<=b) return sum[k];
int ret=;
if(a<=mid) (ret+=query(a,b,lc))%=p;
if(b>mid) (ret+=query(a,b,rc))%=p;
return ret;
}
}
using namespace SegmentTree; int main()
{
scanf("%d%d%d%d",&n,&m,&p,&c);
for(int i=;i<=n;i++)
scanf("%d",&dat[i]);
phi[]=p;
while(phi[cnt]!=)
cnt++,phi[cnt]=getphi(phi[cnt-]);
//要迭代到phi(1)=1,而不能仅迭代到phi(2)=1
//否则在x=0时最后一层会出现c%2
phi[++cnt]=;PRE(); build(,,n);
while(m--)
{
int op,l,r;
scanf("%d%d%d",&op,&l,&r);
if(!op) modify(l,r,,,n);
else printf("%d\n",query(l,r,,,n));
}
return ;
}
[BZOJ 4809] 相逢是问候的更多相关文章
- BZOJ:4869: [Shoi2017]相逢是问候
4869: [Shoi2017]相逢是问候 先说点正经的…… 显然做了有限次(我只知道是有限次,而且不会大,别人说是log次?)修改以后会达到不动点,即以后怎么修改都不变了. 然后就随便做了.(3个l ...
- bzoj 4869: [Shoi2017]相逢是问候 [扩展欧拉定理 线段树]
4869: [Shoi2017]相逢是问候 题意:一个序列,支持区间\(a_i \leftarrow c^{a_i}\),区间求和.在模p意义下. 类似于开根操作,每次取phi在log次后就不变了. ...
- 【BZOJ4869】相逢是问候(线段树,欧拉定理)
[BZOJ4869]相逢是问候(线段树,欧拉定理) 题面 BZOJ 题解 根据欧拉定理递归计算(类似上帝与集合的正确用法) 所以我们可以用线段树维护区间最少的被更新的多少次 如果超过了\(\varph ...
- [BZOJ4869][六省联考2017]相逢是问候(线段树+扩展欧拉定理)
4869: [Shoi2017]相逢是问候 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1313 Solved: 471[Submit][Stat ...
- 【BZOJ4869】相逢是问候 [线段树][欧拉定理]
相逢是问候 Time Limit: 40 Sec Memory Limit: 512 MB[Submit][Status][Discuss] Description Informatikverbin ...
- 洛谷 P3747 [六省联考2017]相逢是问候 解题报告
P3747 [六省联考2017]相逢是问候 题目描述 \(\text {Informatik verbindet dich und mich.}\) 信息将你我连结. \(B\) 君希望以维护一个长度 ...
- 2017 [六省联考] T2 相逢是问候
4869: [Shoi2017]相逢是问候 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1205 Solved: 409[Submit][Stat ...
- 洛谷P3747 [六省联考2017]相逢是问候
传送门 题解 扩展欧拉定理. 线段树维护,已经全改到底了的节点就不管,不然暴力修改下去. //Achen #include<algorithm> #include<iostream& ...
- bzoj千题计划271:bzoj4869: [六省联考2017]相逢是问候
http://www.lydsy.com/JudgeOnline/problem.php?id=4869 欧拉降幂+线段树,每个数最多降log次,模数就会降为1 #include<cmath&g ...
随机推荐
- D. Makoto and a Blackboard(积性函数+DP)
题目链接:http://codeforces.com/contest/1097/problem/D 题目大意:给你n和k,每一次可以选取n的因子代替n,然后问你k次操作之后,每个因子的期望. 具体思路 ...
- WeX5入门之HelloWorld
学习目标:数据双向绑定 在ui2上右键 新建一个应用 然后会出现一个目录 右键hello 在创建页面 选择标准的空白模板 并起一个名 自动生成这两个文件 建立一个input组件 再建一个output组 ...
- Android音视频点/直播模块开发实践总结-zz
随着音视频领域的火热,在很多领域(教育,游戏,娱乐,体育,跑步,餐饮,音乐等)尝试做音视频直播/点播功能.那么作为开发一个小白,如何快速学习音视频基础知识,了解音视频编解码的传输协议,编解码方式,以及 ...
- mysql条件查询中AND与OR联合使用的注意事项!
mysql查询中经常会用到AND与OR一起使用的情况,可如果写法不对,往往会起到相反的效果,这不,前几天就碰到了,最后测试果然提了一堆bug!!!! 废话就不多说了,主要总结一下几点: 一 当mysq ...
- Django中六个常用的自定义装饰器
装饰器作用 decorator是当今最流行的设计模式之一,很多使用它的人并不知道它是一种设计模式.这种模式有什么特别之处? 有兴趣可以看看Python Wiki上例子,使用它可以很方便地修改对象行为, ...
- ubuntu git 简单入门【转】
转自:http://blog.chinaunix.net/uid-20718384-id-3334859.html 1. 安装 sudo apt-get install git-core 2. 初始 ...
- Linux触摸屏驱动测试程序范例【转】
转自:http://blog.sina.com.cn/s/blog_4b4b54da0102viyl.html 转载2015-05-09 16:28:27 标签:androiditlinux 触摸屏驱 ...
- MyEclipse文本对比界面样式修改
MyEclipse刚安装好,使用文件对比的时候,发现两边的对比颜色非常浅,不同的地方不容易发现,可以通过以下配置将显示颜色调深一点. 配置 效果
- 使用gradle编译安卓APK
一.安装JDK 在安装Gradle之前需要先安装JDK,由于安装的是Gradle是4.4所以需要安装JDK1.8. 之前编译总是提示如下错误就是由于先安装的jdk1.7然后安装的1.8造成的,在Gra ...
- php修改文件上传大小限制
上传一个20M文件的时候php报如下错误,是php上传文件大小限制引起 POST Content-Length of 19248654 bytes exceeds the limit of 83886 ...