题目大意:给你一个序列,需要支持区间修改,以及查询一段区间$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]炸脖龙 (线段树+拓展欧拉定理)的更多相关文章

  1. [洛谷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+ ...

  2. BZOJ5394: [Ynoi2016]炸脖龙(欧拉广义降幂)

    就是让你求这个: 传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=5394 解题思路: NOIP2018后第一道题,感觉非常像那个上帝与集合的 ...

  3. P4118 [Ynoi2016]炸脖龙I

    思路:扩展欧拉定理 提交:\(\geq5\)次 错因:快速幂时刚开始没有判断\(a\)是否大于\(p\) 题解: 用树状数组维护差分,查询时暴力从左端点的第一个数向右端点递归,若递归时发现指数变为\( ...

  4. Luogu P4118 [Ynoi2016]炸脖龙I

    题目 首先考虑没有修改的情况.显然直接暴力扩展欧拉定理就行了,单次复杂度为\(O(\log p)\)的. 现在有了修改,我们可以树状数组维护差分数组,然后\(O(\log n)\)地单次查询单点值. ...

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

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

  6. [BZOJ 2212] [Poi2011] Tree Rotations 【线段树合并】

    题目链接:BZOJ - 2212 题目分析 子树 x 内的逆序对个数为 :x 左子树内的逆序对个数 + x 右子树内的逆序对个数 + 跨越 x 左子树与右子树的逆序对. 左右子树内部的逆序对与是否交换 ...

  7. [BZOJ 3995] [SDOI2015] 道路修建 【线段树维护连通性】

    题目链接:BZOJ - 3995 题目分析 这道题..是我悲伤的回忆.. 线段树维护连通性,与 BZOJ-1018 类似,然而我省选之前并没有做过  1018,即使它在 ProblemSet 的第一页 ...

  8. [BZOJ 3888] [Usaco2015 Jan] Stampede 【线段树】

    题目链接:BZOJ - 3888 题目分析 首先,计算出每个线段在 x 坐标 0 处出现的时间开始点和结束点,就转成了时间轴上的线段. 然后就是看每条线段是否被 y 比它小的线段完全覆盖了.注意求出的 ...

  9. [BZOJ 3747] [POI 2015] Kinoman【线段树】

    Problem Link : BZOJ 3747 题解:ZYF-ZYF 神犇的题解 解题的大致思路是,当区间的右端点向右移动一格时,只有两个区间的左端点对应的答案发生了变化. 从 f[i] + 1 到 ...

随机推荐

  1. Kattis - How Many Digits?

    How Many Digits? Often times it is sufficient to know the rough size of a number, rather than its ex ...

  2. struts中请求数据自动封装

    实现原理 参数拦截器 第一:jsp表单数据填充到action中的属性 必须实现set方法,get方法可以不需要实现,jsp页面name名字保持一致 第二:jsp表单填充到action的对象的属性 js ...

  3. Spark作业执行

    Spark中一个action触发一个job的执行,在job提交过程中主要涉及Driver和Executor两个节点. Driver主要解决 1. RDD 依赖性分析,生成DAG. 2. 根据RDD D ...

  4. BZOJ 2631 [国家集训队]Tree II (LCT)

    题目大意:给你一棵树,让你维护一个数据结构,支持 边的断,连 树链上所有点点权加上某个值 树链上所有点点权乘上某个值 求树链所有点点权和 (辣鸡bzoj又是土豪题,洛谷P1501传送门) LCT裸题, ...

  5. jquery weui ajax滚动加载更多

    手机端使用jquery weui制作ajax滚动加载更多. 演示地址:http://wx.cnkfk.com/nuol/static/fpage.html 代码: <!DOCTYPE html& ...

  6. Android学习之GridView图片布局适配经验

    開始解说这篇博客之前,我想问一下,当布局相似GridView这样的多列布局时,我们该怎么布局,才干更好的去适配呢? 扣张图来展示一下 比如这样的需求,三张图片均分屏幕 实现方法: 1.切图固定,比如是 ...

  7. [ReactVR] Start a Virtual Reality Project Using the React VR CLI

    We will learn how to set up a React VR project, run the development mode with hot reloading, and tak ...

  8. HDU 4175 Class Schedule (暴力+一点dp)

    pid=4175">HDU 4175 题意:有C座楼,每座楼有T个教室.一个人须要訪问C个教室.每座楼仅仅能訪问一个教室. 訪问教室须要消耗能量,从x点走到y点须要消耗abs(x-y) ...

  9. 37、ifconfig命令

    很多windows很熟悉ipconfig命令行工具.它被用来获取网络接口配置信息并对此进行改动.Linux系统拥有一个类似的工具,也就是ifconfig(interfaces config). 通常须 ...

  10. 指向类成员函数的函数指针及#define typedef 实现类成员函数的类型转换

    #include <iostream> using namespace std; class Test { public : void print() { cout << &q ...