当前位置: 首页 > news >正文

P3934 [Ynoi Easy Round 2016] 炸脖龙 I 做题记录

前置芝士:扩展欧拉定理

题目大意

给一个长为 \(n\) 的序列,\(m\) 次操作,每次操作:

  1. 区间 \([l,r]\)\(x\)
  2. 对于区间 \([l,r]\),查询:

\[{a_l}^{{a_{l+1}}^{{a_{l+2}}^{{\dots} ^{a{r}}}}} \mod p \]

思路

首先我们有:

\[a^k\equiv \left\{\begin{matrix}a^k, & k<p\\ a^{(k\bmod {\varphi(p)})+\varphi(p)}, & k\ge p\end{matrix}\right.\ \pmod p \]

注意到这两个情况不可以合并,可以举出反例:\(a=2,k=2,p=16\) 时,\(a^k \bmod p =4\),而 \(a^{(k\bmod \varphi(p))+\varphi(p)} \bmod p = 0\)

我们考虑询问怎么解决。首先有 \({a_l}^{{a_{l+1}}^{{\dots}^{a_r}}} \bmod p\),我们可以把上面那一大坨先放到扩展欧拉定理里面,递归解决。

我们记录真实值和取模后的值。特殊的,当真实值被设为 \(-1\) 时则代表以及超过模数,使用下面的情况。

首先特判当 \(p=1\) 时可以直接返回 \(0\)(取模后的值)和 \(1\) (真实值);然后特判 \(a\)\(1\) 的情况,因为当 \(a\)\(1\) 时,当前情况不管 \(p\) 为啥都真实值和取模后的值都为 \(1\),所以一定是归类在第一种里面。

看到这里我们来证明一下时间复杂度。

我们对 \(\varphi(p)\) 进行讨论:

  • \(\varphi(p)\) 为质数时:
    • \(p=2,\varphi(p)=1\),此时下一轮一定会停止递归。
    • \(p\ne 2,\varphi(p)=p-1\),此时下一轮 \(p\)(此时的 \(\varphi(p)\))一定为偶数。
  • \(\varphi(p)\) 不为质数时:
    • \(p\) 为偶数时,根据欧拉函数的计算公式,对于 \(p=\prod_{i=1}^{x} {c_i}^{d_i}(c_i>1)\)\(\varphi(p)=p\times \prod_{i=1}^{x}\frac{c_i-1}{c_i}\),因为 \(p\) 为偶数,即一定有一个 \(c_i=2\),则 \(p\) 至少会减少 \(\frac12\)
    • \(p\) 为奇数时,根据欧拉函数的计算公式,对于 \(p=\prod_{i=1}^{x} {c_i}^{d_i}(c_i>1)\)\(\varphi(p)=p\times \prod_{i=1}^{x}\frac{c_i-1}{c_i}\),因为 \(p\) 为奇数且 \(p\) 不为质数,即一定有一个奇数 \(c_i\) 且没有偶数 \(c_i\),又因为 \(c_i-1\) 一定为偶数,则下一轮 \(p\)(此时的 \(\varphi(p)\))一定为偶数。

综上,我们证明了两次操作之后,\(p\) 一定会乘上 \(\frac12\)。所以说一次询问的递归层数为 \(O(\log p)\) 层。而快速幂的时间复杂度为 \(O(\log V)\)\(V\) 为值域),则每次查询时间复杂度为 \(O(\log p\log V)\)

对于快速求欧拉函数,因为 \(p\in[1,2\times 10^7]\),我们可以预处理出这个范围里的欧拉函数值。时间复杂度 \(O(n)\)

时间复杂度:\(O(m\log p\log V)\)

点击查看代码
#include<bits/stdc++.h>#define int i128
#define pii pair<int,int> 
#define pll pair<long long,long long> 
#define ll long long
#define i128 __int128#define mem(a,b) memset((a),(b),sizeof(a))
#define m0(a) memset((a),0,sizeof(a))
#define m1(a) memset(a,-1,sizeof(a))
#define lb(x) ((x)&-(x))
#define lc(x) ((x)<<1)
#define rc(x) (((x)<<1)|1)
#define pb(G,x) (G).push_back((x))
#define For(a,b,c) for(int a=(b);a<=(c);a++)
#define Rep(a,b,c) for(int a=(b);a>=(c);a--)
#define in1(a) a=read()
#define in2(a,b) a=read(), b=read()
#define in3(a,b,c) a=read(), b=read(), c=read()
#define in4(a,b,c,d) a=read(), b=read(), c=read(), d=read()
#define fst first 
#define scd second 
#define dbg puts("IAKIOI")using namespace std;int read() {int x=0,f=1; char c=getchar();for(;c<'0'||c>'9';c=getchar()) f=(c=='-'?-1:1); for(;c<='9'&&c>='0';c=getchar()) x=(x<<1)+(x<<3)+(c^48);return x*f;
}
void write(int x) { if(x>=10) write(x/10); putchar('0'+x%10); }const int mod = 998244353;
pii qpo(int a,int b,int mod,int opt) {a%=mod; pii res={1,opt?1:0};int B=b;if(a>1) while(res.second*a<mod&&B) B--,res.second*=a;if(!B&&opt) {res.first=res.second; return res;}res.second=-1;for(;b;b>>=1,a=(a*a)%mod) if(b&1) res.first=res.first*a%mod; return res; 
}
int inv(int a) {return qpo(a,mod-2,mod,1).fst; }#define maxn 500050int n,m,a[maxn];struct Bit {int c[maxn];void add(int x,int val) {for(;x<maxn;x+=lb(x)) c[x]+=val;}int query(int x) {int res=0;for(;x;x-=lb(x)) res+=c[x];return res;}void alr(int l,int r,int val) {add(l,val); add(r+1,-val);}
}Tr;vector<int> pri;
bool pr[20007000];
int phi[20007000];void pre(int n) {phi[1]=1;For(i,2,n) {if(!pr[i]) phi[i]=i-1,pri.push_back(i);for(auto x:pri) {if(i*x>n) break;pr[i*x]=1;if(i%x==0) {phi[i*x]=phi[i]*x; break;}phi[i*x]=phi[i]*phi[x];}}
}pii dfs(int idx,int lim,int p) {
//	cout<<(ll)idx<<' '<<(ll)Tr.query(idx)<<' '<<(ll)lim<<' '<<(ll)p<<' '<<(ll)phi[p]<<'\n';if(idx==lim) return {Tr.query(idx)%p,Tr.query(idx)>=p?-1:Tr.query(idx)};if(Tr.query(idx)<=1&&p>1) return {Tr.query(idx),Tr.query(idx)};if(p==1) return {0,-1};	pii nxt=dfs(idx+1,lim,phi[p]);pii res=qpo(Tr.query(idx),(nxt.scd>=p||nxt.scd<0)?((nxt.fst%phi[p])+phi[p]):nxt.fst,p,nxt.scd>=0?1:-1); 
//	cout<<"idx:"<<(ll)idx<<" res:"<<(ll)res.fst<<'\n';return res;
}void work() {in2(n,m); pre(20000000);For(i,1,n) {in1(a[i]); Tr.add(i,a[i]); Tr.add(i+1,-a[i]);}while(m--) {int opt,l,r,x;in4(opt,l,r,x);if(opt==1) Tr.alr(l,r,x);else {write(dfs(l,r,x).fst); putchar('\n');}}
}signed main() {
//	freopen("data.in","r",stdin);
//	freopen("myans.out","w",stdout);
//	ios::sync_with_stdio(false); 
//	cin.tie(0); cout.tie(0);double stt=clock();int _=1;
//	_=read();
//	cin>>_;For(i,1,_) {work();}cerr<<"\nTotal Time is:"<<(clock()-stt)*1.0/1000<<" second(s)."<<'\n';return 0;
}
http://www.hskmm.com/?act=detail&tid=8561

相关文章:

  • 【CompletableFuture 核心操作全解】详细注释版
  • 关于学术不端的一些思考
  • python基础-字典
  • pod 内nslookup请求时常异常
  • 单调队列优化DP
  • 4.5.11版本闪亮登场~快来看看有哪些新功能
  • 教你数分钟内创建并运行一个 DolphinScheduler Workflow!
  • AT_agc065_b [AGC065B] Erase and Insert
  • 《大模型时代——智能体的崛起与应用实践(微课视频版)》
  • 第三节:GoLangChain提示词(Prompts)处理详解
  • rhel8 中vdo 邏輯卷的邏輯擴容
  • Codeforces Round 1051 (Div. 2) 部分题解
  • kingbase金仓数据库的密码有效期和密码复杂度
  • HDF5文件
  • Error encountered when performing Introspect the Portion of idea Introspect using JDBC metadata在哪设置
  • 核桃 CSP-S 模拟
  • 正确输入连字号、连接号、破折号和负号
  • 9 月记录
  • python基础-元组
  • .net core中获得程序集以及注入框架的方法总结
  • python基础篇-list(列表)
  • vscode使用powershell中文乱码
  • 关于如何读懂 P11832 [省选联考 2025] 图排列?
  • Untitled
  • 敏感性分析
  • 完整教程:论园区电气安全管理系统的重要性
  • 基于CSU8RP1186芯片的握力器解决方案
  • 亮相2025年服贸会,天翼云打造高质量算力服务新生态!
  • 易路薪酬专家Agent:基于10亿级数据与AI的智能薪酬解决方案
  • 有点意思!Java8后最有用新特性排行榜!