BZOJ 5394 [Ynoi2016]炸脖龙 (线段树+拓展欧拉定理)
题目大意:给你一个序列,需要支持区间修改,以及查询一段区间$a_{i}^{a_{i+1}^{a_{i+2}...}}mod\;p$的值,每次询问的$p$的值不同
对于区间修改,由线段树完成,没什么好说的
对于查询,利用"上帝与集合的正确用法"那道题的方法,不断取$\phi(p)$降幂,那么最多迭代$log$层
由于$ai$不一定和$p$互质,需要使用拓展欧拉定理
$ans=ai^{Ans_{i+1}\;mod\;\phi(p)+Ans_{i+1}>=\phi(p)?\phi(p):0}$
每层都记录$Ans_{i}$是否对这一层的$p$取过模,用于判断Ans_{i+1}>=\phi(p)
特判比较多,注意特判的优先级
1.如果$ai mod p==0$,那么不论接下来是几次幂都返回0
2.如果$ai==1$,那么不论$ai$的多少次幂都是1,同时清空已经取过模的标记
3.如果$i+1$层取过模,那么这一层的运算即使没取模也要标记为取过模,因为实际值一定取模了
4.如果$i+1$层取过模,那么快速幂里需要加上$\phi(p)$,反之$i+1$没取模一定不要加,不然答案是错的
5.接下来在快速幂里更新第i层计算的取模标记
#include <cstdio>
#include <cstring>
#include <algorithm>
#define NN 501000
#define MM 20001000
#define maxn 20000000
#define ll long long
#define uint unsigned int
#define ull unsigned long long
using namespace std; int n,m,g,r,root;
int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
}
int use[MM],pr[],phi[MM],cnt;
void Pre()
{
phi[]=;
for(int i=;i<=maxn;i++)
{
if(!use[i]) pr[++cnt]=i,phi[i]=i-;
for(int j=;j<=cnt&&i*pr[j]<=maxn;j++){
use[i*pr[j]]=;
if(i%pr[j]) phi[i*pr[j]]=phi[i]*phi[pr[j]];
else {phi[i*pr[j]]=phi[i]*pr[j];break;}
}
}
}
struct Seg{
ull val[NN<<],tag[NN<<];
void pushdown(int rt){
if(!tag[rt]) return;
val[rt<<]+=tag[rt],val[rt<<|]+=tag[rt];
tag[rt<<]+=tag[rt],tag[rt<<|]+=tag[rt];
tag[rt]=;
}
void update(int L,int R,int l,int r,int rt,int w)
{
if(L<=l&&r<=R){tag[rt]+=w,val[rt]+=w;return;}
int mid=(l+r)>>;pushdown(rt);
if(L<=mid) update(L,R,l,mid,rt<<,w);
if(R>mid) update(L,R,mid+,r,rt<<|,w);
//pushup(rt);
}
ull query(int x,int l,int r,int rt)
{
if(l==r) return val[rt];
int mid=(l+r)>>;pushdown(rt);
if(x<=mid) return query(x,l,mid,rt<<);
else return query(x,mid+,r,rt<<|);
//pushup(rt);
}
}s;
ull qpow(ull x,ull y,int p,int &fl)
{
ull ans=;
if(y==) return ;
if(x>=p) x%=p,fl=;
while(y){
if(y&){
if(ans*x>=p)
ans=ans*x%p,fl=;
else ans=ans*x;
}
if(x*x>=p)
x=x*x%p,fl=;
else x=x*x;
y>>=;
}return ans;
}
ull euler(int i,int ma,int p,int &fl)
{
ull ai=s.query(i,,n,);
if(p==) {fl=;return ;}
if(ai>=p) fl=;
if(ai%p==) return ;
if(ai==) {fl=;return ;}
int o=;ai%=p;
if(i==ma) return ai;
ull ans=euler(i+,ma,phi[p],o);
if(o==) fl=;
/*if(ans==0){
if(o){
if(ai%p==0) {return 0;}
else return qpow(ai,ans+phi[p],p,fl);
}else{
return 1;
}
}else{
if(o) return qpow(ai,ans+phi[p],p,fl);
else return qpow(ai,ans,p,fl);
}*/
if(ans==&&o&&ai==) return ;
else if(o) return qpow(ai,ans+phi[p],p,fl);
else return qpow(ai,ans,p,fl);
} int main()
{
//freopen("t2.in","r",stdin);
//freopen("testdata.in","r",stdin);
//freopen("a.out","w",stdout);
int fl,x,y,z;
scanf("%d%d",&n,&m);
Pre();
for(int i=;i<=n;i++)
x=gint(),s.update(i,i,,n,,x);
for(int i=;i<=m;i++)
{
fl=gint(),x=gint(),y=gint(),z=gint();
if(fl==){
s.update(x,y,,n,,z);
}else{
int fl=;
printf("%llu\n",euler(x,y,z,fl));
}
}
return ;
}
BZOJ 5394 [Ynoi2016]炸脖龙 (线段树+拓展欧拉定理)的更多相关文章
- [洛谷P4118][Ynoi2016]炸脖龙I([洛谷P3934]Nephren Ruq Insania)
题目大意:有$n$个数,每个数为$s_i$,两个操作: $1\;l\;r\;x:$表示将区间$[l,r]$内的数加上$x$ $2\;l\;r\;p:$表示求$s_l^{s_{l+1}^{^{s_{l+ ...
- BZOJ5394: [Ynoi2016]炸脖龙(欧拉广义降幂)
就是让你求这个: 传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=5394 解题思路: NOIP2018后第一道题,感觉非常像那个上帝与集合的 ...
- P4118 [Ynoi2016]炸脖龙I
思路:扩展欧拉定理 提交:\(\geq5\)次 错因:快速幂时刚开始没有判断\(a\)是否大于\(p\) 题解: 用树状数组维护差分,查询时暴力从左端点的第一个数向右端点递归,若递归时发现指数变为\( ...
- Luogu P4118 [Ynoi2016]炸脖龙I
题目 首先考虑没有修改的情况.显然直接暴力扩展欧拉定理就行了,单次复杂度为\(O(\log p)\)的. 现在有了修改,我们可以树状数组维护差分数组,然后\(O(\log n)\)地单次查询单点值. ...
- 【BZOJ4869】相逢是问候(线段树,欧拉定理)
[BZOJ4869]相逢是问候(线段树,欧拉定理) 题面 BZOJ 题解 根据欧拉定理递归计算(类似上帝与集合的正确用法) 所以我们可以用线段树维护区间最少的被更新的多少次 如果超过了\(\varph ...
- [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】
题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换 ...
- [BZOJ 3995] [SDOI2015] 道路修建 【线段树维护连通性】
题目链接:BZOJ - 3995 题目分析 这道题..是我悲伤的回忆.. 线段树维护连通性,与 BZOJ-1018 类似,然而我省选之前并没有做过 1018,即使它在 ProblemSet 的第一页 ...
- [BZOJ 3888] [Usaco2015 Jan] Stampede 【线段树】
题目链接:BZOJ - 3888 题目分析 首先,计算出每个线段在 x 坐标 0 处出现的时间开始点和结束点,就转成了时间轴上的线段. 然后就是看每条线段是否被 y 比它小的线段完全覆盖了.注意求出的 ...
- [BZOJ 3747] [POI 2015] Kinoman【线段树】
Problem Link : BZOJ 3747 题解:ZYF-ZYF 神犇的题解 解题的大致思路是,当区间的右端点向右移动一格时,只有两个区间的左端点对应的答案发生了变化. 从 f[i] + 1 到 ...
随机推荐
- Unity 动画资源与模型资源的区别
动画资源: 模型资源: 对比: 模型文件多出来了 Materials + 贴图 + mesh文件,少了avatar文件 PS:动画资源,是指动画片段,即animation chip,它一般包含在模型资 ...
- zookeeper+kafka集群搭建
一.ZK集群安装. 解压安装包后进入conf目录,conf/zoo_sample.cfg拷贝一份命名为zoo.cfg,同时也放在conf下面. zookeeper配置文件: # The number ...
- 解决PL/SQL管理工具database下拉为空和登录出现ORA-12154
前言:昨天捣鼓了一下午,终于可以用plsql连接上oracle了... 测试环境:win10 注意问题: (一).环境变量 我发现按网上别人说的那一大推环境配置,很容易出错,我把它们全删了,就留了两个 ...
- 给iview组件select设置默认值
1.首先,给select加一个v-model,如: <Select v-model="exam_name" > <Option v-for="(item ...
- 浅谈optparse 解析命令行参数库
使用的背景 在工作中我们经常要制定运行脚本的一些参数,因为有些东西是随着我么需求要改变的,所以在为们写程序的时候就一定不能把写死,这样我们就要设置参数 在python中我们可以通过sys 模板的arg ...
- PHP中的 Iterator 与 Generator
在讲解生成器之前先介绍一下迭代器: 在 PHP 中,通常情况下遍历数组使用 foreach 来遍历. 如果我们要想让一个对象可以遍历呢? PHP 为我们提供了 Iterator 接口,只要实现了这个接 ...
- 小试牛刀之sort()排序的实现
受大学室友的鼓动,我也打算利用公众平台来记录自己的前端知识积累,同时呢,自己总结的东西,总归会有局限性,希望小伙伴能给我指点迷津.知识就是一张巨大的网,作为一名摸不清头绪的入学者,唯一能做的事情就是吐 ...
- pytorch 1 torch_numpy, 对比
import torch import numpy as np details about math operation in torch can be found in: http://pytorc ...
- 【转载】SQLITE3 使用总结
转载自网友董淳光的文章. 前序: 这里要注明,我是一个跨平台专注者,并不喜欢只用 windows 平台.我以前的工作就是为 unix 平台写代码.下面我所写的东西,虽然没有验证,但是我已尽量不使用任何 ...
- html5中调用摄像头拍照
方法: getCamera: 获取摄像头管理对象 对象: Camera: 摄像头对象 CameraOption: JSON对象.调用摄像头的參数 PopPosition: JSON对象,弹出拍照或摄像 ...