https://www.luogu.org/problemnew/show/P3934

题面自己读吧(滑稽。

看到这道题就能够想到BZOJ4869:[SHOI2017]相逢是问候我们曾经用过的哲学扩展欧拉定理。

(咦什么时候这个东西都普及到noip了好方啊)

也就是说,不论询问的区间[l,r]长度有多大,实际上我们暴力算只需要logp次模数就变成了1之后的询问就不需要担心了。

区间修改可以线段树/树状数组来干。

敲完发现是70pts,很难受。

有没有发现这个公式前面有一个前提?其实,当a^b<p的时候,a的指数就不应当加phi(p)了,这也就是错的原因。

我们当然可以每次传递当前的b是否曾经对phi(p)取过模来决定是否加phi(p),经过多次修改之后终于AC了……

PS:请注意我们运算的时候很可能出现x^0%x=1这种情况,而显然我们希望的答案应当为0(虽然我并不知道为什么),所以需要特判之。

#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e5+;
const int M=2e7+;
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;
}
bool ok[N];
ll qpow(ll k,ll n,int p,int l){
ll res=;
while(n){
if(n&){
res*=k;
if(res>=p)ok[l]=,res%=p;
}
k*=k;n>>=;
if(k>=p)ok[l]=,k%=p;
}
return res;
}
int n,m;
int su[M],he[M],phi[M],tot;
ll tr[N*],lz[N*],b[N];
void Euler(int n){
phi[]=;
for(int i=;i<=n;i++){
if(!he[i])su[++tot]=i,phi[i]=i-;
for(int j=;j<=tot;j++){
if(i*su[j]>n)break;
he[i*su[j]]=;
if(i%su[j]==){
phi[i*su[j]]=phi[i]*su[j];
break;
}else phi[i*su[j]]=phi[i]*phi[su[j]];
}
}
}
inline void push(int a,int l,int r){
if(!lz[a])return;
int mid=(l+r)>>;
lz[a<<]+=lz[a];lz[a<<|]+=lz[a];
if(l==mid)tr[a<<]+=lz[a];
if(mid+==r)tr[a<<|]+=lz[a];
lz[a]=;
}
void build(int a,int l,int r){
if(l==r){
tr[a]=b[l];return;
}
int mid=(l+r)>>;
build(a<<,l,mid);build(a<<|,mid+,r);
}
void add(int a,int l,int r,int l1,int r1,int x){
if(r<l1||r1<l)return;
if(l1<=l&&r<=r1){
lz[a]+=x;
if(l==r)tr[a]+=x;
return;
}
push(a,l,r);
int mid=(l+r)>>;
add(a<<,l,mid,l1,r1,x);add(a<<|,mid+,r,l1,r1,x);
}
ll ask(int a,int l,int r,int k){
if(l==r)return tr[a];
push(a,l,r);
int mid=(l+r)>>;
if(k<=mid)return ask(a<<,l,mid,k);
else return ask(a<<|,mid+,r,k);
}
ll query(int l,int r,int p){
ok[l]=;
ll ans=ask(,,n,l);
if(ans>=p)ok[l]=;
if(ans%p==)return ;
if(p==)return ;
ans%=p;
if(l==r)return ans;
ll tmp=query(l+,r,phi[p]);
return qpow(ans,tmp+(ok[l+]?phi[p]:),p,l);
}
int main(){
Euler(2e7);
n=read(),m=read();
for(int i=;i<=n;i++)b[i]=read();
build(,,n);
for(int i=;i<=m;i++){
int op=read();
if(op==){
int l=read(),r=read(),x=read();
add(,,n,l,r,x);
}else{
int l=read(),r=read(),p=read();
printf("%lld\n",query(l,r,p));
}
}
return ;
}

当然还有另外一种(正解)的做法。

考虑到假设我们暴力枚举模拟前几次操作之后,往后的操作基本都是大于phi(p)的,而没有加phi(p)的只可能是前面几项。

故暴力处理前面几项即可,常数显然要比上面的方法要大很多。

#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e5+;
const int M=2e7+;
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;
}
int qpow(int k,ll n,int p){
int res=;
while(n){
if(n&)res=(ll)res*k%p;
k=(ll)k*k%p;n>>=;
}
return res;
}
int n,m,tag[N];
int su[M],he[M],phi[M],tot;
ll tr[N*],lz[N*],b[N];
void Euler(int n){
phi[]=;
for(int i=;i<=n;i++){
if(!he[i])su[++tot]=i,phi[i]=i-;
for(int j=;j<=tot;j++){
if(i*su[j]>n)break;
he[i*su[j]]=;
if(i%su[j]==){
phi[i*su[j]]=phi[i]*su[j];
break;
}else phi[i*su[j]]=phi[i]*phi[su[j]];
}
}
}
inline void push(int a,int l,int r){
if(!lz[a])return;
int mid=(l+r)>>;
lz[a<<]+=lz[a];lz[a<<|]+=lz[a];
if(l==mid)tr[a<<]+=lz[a];
if(mid+==r)tr[a<<|]+=lz[a];
lz[a]=;
}
inline void build(int a,int l,int r){
if(l==r){
tr[a]=b[l];return;
}
int mid=(l+r)>>;
build(a<<,l,mid);build(a<<|,mid+,r);
}
inline void add(int a,int l,int r,int l1,int r1,int x){
if(r<l1||r1<l)return;
if(l1<=l&&r<=r1){
lz[a]+=x;
if(l==r)tr[a]+=x;
return;
}
push(a,l,r);
int mid=(l+r)>>;
add(a<<,l,mid,l1,r1,x);add(a<<|,mid+,r,l1,r1,x);
}
inline ll ask(int a,int l,int r,int k){
if(l==r)return tr[a];
push(a,l,r);
int mid=(l+r)>>;
if(k<=mid)return ask(a<<,l,mid,k);
else return ask(a<<|,mid+,r,k);
}
inline ll qry(int l){
if(tag[l]==m)return b[l];
tag[l]=m;
return b[l]=ask(,,n,l);
}
inline ll query(int l,int r,int p){
ll ans=qry(l);
if(ans%p==)return ;
if(p==)return ;
if(l==r)return (ans%p+(ans>p)*p)%p;
int f=min(r,l+);
for(int i=l+;i<=f;i++){
if(qry(i)==){
f=i;break;
}
}
ll t=qry(f),q=;
for(int i=f-;i>=l+;i--){
q=t,t=;
ll tmp=qry(i);
while(q--){
t*=tmp;
if(t>=phi[p])return qpow(ans%p,query(l+,r,phi[p])+phi[p],p);
}
}
return qpow(ans%p,t,p);
}
int main(){
Euler(2e7);memset(tag,-,sizeof(tag));
n=read(),m=read();
for(int i=;i<=n;i++)b[i]=read();
build(,,n);
while(m--){
int op=read();
if(op==){
int l=read(),r=read(),x=read();
add(,,n,l,r,x);
}else{
int l=read(),r=read(),p=read();
printf("%lld\n",query(l,r,p));
}
}
return ;
}

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

+本文作者:luyouqi233。               +

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

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

洛谷3934:Nephren Ruq Insania——题解的更多相关文章

  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. [洛谷3934]P3934 Nephren Ruq Insania题解

    先放个奈芙莲 解法 看到这种题目就知道是欧拉降幂,然后根据某玄学证明,递归欧拉降幂从l到r不会超过\(\Theta(log_n)\),所以直接递归解决,然后区间修改直接树状数组维护一下 然后就A了 代 ...

  3. Luogu 3934 Nephren Ruq Insania

    和Ynoi2016 炸脖龙重题了. BZOJ 5394. 首先是扩展欧拉定理: 一开始傻掉了……递归的层数和区间长度无关……也就是说我们每一次直接暴力递归求解子问题一定不会超过$logP$层,因为当模 ...

  4. 洛谷P1783 海滩防御 分析+题解代码

    洛谷P1783 海滩防御 分析+题解代码 题目描述: WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和 ...

  5. 洛谷P4047 [JSOI2010]部落划分题解

    洛谷P4047 [JSOI2010]部落划分题解 题目描述 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落 ...

  6. 洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈)

    洛谷P1155 双栈排序题解(图论模型转换+二分图染色+栈) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1311990 原题地址:洛谷P1155 双栈排序 ...

  7. 洛谷10月月赛II题解

    [咻咻咻] (https://www.luogu.org/contestnew/show/11616) 令人窒息的洛谷月赛,即将参加NOIp的我竟然只会一道题(也可以说一道也不会),最终145的我只能 ...

  8. [洛谷P1823]音乐会的等待 题解(单调栈)

    [洛谷P1823]音乐会的等待 Description N个人正在排队进入一个音乐会.人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人.队列中任意两个人A和B,如果他们是相邻或他们之间没 ...

  9. BZOJ2527 & 洛谷3527:[Poi2011]Meteors——题解

    +++++++++++++++++++++++++++++++++++++++++++ +本文作者:luyouqi233. + +欢迎访问我的博客:http://www.cnblogs.com/luy ...

随机推荐

  1. iOS SSL Pinning 保护你的 API

    随着互联网的发展,网站全面 https 化已经越来越被重视,做为 App 开发人员,从一开始就让 API 都走 SSL 也是十分必要的.但是光这样就足够了吗? SSL 可以保护线上 API 数据不被篡 ...

  2. 一次IPC无法创建的问题

    背景说明:         后台子系统都是运行在pc上的linux         系统有多个子系统,有一个子系统负责统一启停其他子系统,这里把这个子系统称为olddriver.         ol ...

  3. Appium的环境搭建和配置

    Appium的环境搭建和配置 一.安装Nodejs 下载nodejs安装包(https://nodejs.org/en/download/)安装 下载后,双击安装文件,按提示来安装. 测试安装是否成功 ...

  4. Python简要标准库(1)

    sys sys这个模块让你能够访问与Python解释器联系紧密的变量和函数 其中的一些在下表 F argv 命令行参数,包括脚本名称 exit([arg]) 退出当前的程序,可选参数为给定的返回值或者 ...

  5. python学习笔记04 --------------基本运算符

    1.算数运算 + 加 - 减 * 乘 /   除 % 取模(先做除法,然后返回余数) ** 乘方(幂运算) //          取整(相除,然后返回商的整数部分) 2.比较运算(返回布尔值) == ...

  6. CsvHelper文档-1前言

    CsvHelper文档-1前言 英文文档链接地址:CsvHelper Document 开源项目地址:CsvHelper 翻译于2018-1-5,原本可能会随时更新: 每一段代码都是经过我实际测试的, ...

  7. python简单循环生成器

    import time #循环生成器 def traversal_list(alist, i): while True: length = len(alist) i = i%(length) yiel ...

  8. Grid 网格布局

    CSS 网格布局(Grid Layout) 是CSS中最强大的布局系统. 这是一个二维系统,这意味着它可以同时处理列和行,不像 flexbox 那样主要是一维系统. 你可以通过将CSS规则应用于父元素 ...

  9. parity注记词和地址

    remix skilled curled cobweb tactics koala bartender precinct energize exes ridden cohesive 0x00EeC52 ...

  10. c# html 导出word

    [CustomAuthorize]        public FileResult ExportQuestionCenterWord(SearchBaseQuestion search)       ...