Jzoj5636 Power
近期没有写过博客感觉要死了->重返jz深造
一道区间查询的问题,因为模数不是质数,我们考虑利用指数循环节这个东西:
x^k=x^(k%phi(M)+phi(M))%M 这里要求k>=phi(M)
那么可以写成Ans[l,r]%M=x^(Ans[l+1,r]%phi(M))%M
由于phi的迭代会在logn次收敛为1,所以我们可以直接递归来做
先用线性筛筛出10^7以内的phi值,大过这个的就分解质因数来计算
注意一个问题,对于一个询问[l,r],有可能answer[l+1,r]并不能达到phi(M),这个时候就不能使用上面的结论
至于如何判断一个区间的答案是否大过模数,可以做一次不带取模的pow和一次带取模的,如果两次答案不同就说明答案大过模数
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 10000000
#define LL long long
using namespace std;
int n,m,M,s[100010]; bool vis[N+10];
int t=0,w[N>>2],phi[N+10];
inline LL bow(LL x,LL k,LL s=1){
for(;k;x=x*x,k>>=1) k&1?s=s*x:0;
return s;
}
inline LL pow(LL x,LL k,LL M,LL s=1){
for(;k;x=x*x%M,k>>=1) k&1?s=s*x%M:0;
return s;
}
inline int cphi(int M){
int T=M;
for(int i=1;w[i]*w[i]<=M;++i)
if(M%w[i]==0) for(T=T/w[i]*(w[i]-1);M%w[i]==0;M/=w[i]);
if(M>1) T=T/M*(M-1);
return T;
}
inline bool gcd(int l,int r,int M,int& S){
if(M==1){ S=0; return 1; }
if(l==r){ S=s[l]%M; return s[l]>=M; }
int ph=(M<=N?phi[M]:cphi(M));
if(gcd(l+1,r,ph,S)){
S=pow(s[l],ph+S,M);
return s[l]>=1;
} else {
int T=bow(s[l],S);
S=pow(s[l],S,M);
return S!=T;
}
}
int main(){
freopen("power.in","r",stdin);
freopen("power.out","w",stdout);
scanf("%d%d",&n,&M);
for(int i=1;i<=n;++i) scanf("%d",s+i);
for(int i=2;i<=N;++i){
if(!vis[i]) phi[w[++t]=i]=i-1;
for(int j=1;j<=t && i*w[j]<=N;++j){
vis[i*w[j]]=1;
if(i%w[j]==0){ phi[i*w[j]]=phi[i]*w[j]; break; }
phi[i*w[j]]=phi[i]*(w[j]-1);
}
}
scanf("%d",&m);
for(int l,r;m--;){
scanf("%d%d",&l,&r);
gcd(l,r,M,r);
printf("%d\n",r);
}
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 2025成都.NET开发者Connect圆满结束