阶与原根学习笔记
V.阶与原根
实际上这部分内容在OI中应用很少,但它是一些重要思想以及算法的基础。
阶是在互质数 间的定义:满足 的最小 被称作 模 的阶,记作 。
明显,在 不互质时, 的无论多少次幂全都是 的倍数,故不可能取到 ;而当互质时,依据扩展欧拉定理,必有 ,但也不排除存在更小的 。
阶有什么性质呢?
性质1. 模 两两不同余。
如果两个数 同余的话(不妨设 ),则 ,而 ,故只有可能 ,即 ,而 一定是 的,故此时 就不是最小的满足 的 了,与前提矛盾。
性质2.若 ,则 。
这个函数,依照性质1,其最短循环节是 。故所有模 余 的数一定只存在于 倍数的位置。
一个数 被称作 的原根,当且仅当 。
显然,其前提条件是 ,不然 不存在。
原根判定定理: 是 的原根,当且仅当对于一切 的质因数 ,都有 。
原根个数定理:若 有原根,则原根个数是 。
原根存在定理: 有原根,当且仅当 ,其中 是奇质数,。
最小原根级别定理:若 有原根,则最小原根是 级别的。
什么?你问证明?但是考试也不考证明啊(摊手)
原根寻找方法:暴力找到最小原根 ,则对于所有与 互质的 , 都是 的原根。
时间复杂度 。
总结步骤:
- 判断 是否 ,不是则直接返回。
- 预处理 所有质因数。
- 从小到大枚举与 互质的 ,并依次用快速幂检验 所有质因数。
- 找到最小原根,枚举所有与 互质的数,求快速幂即可。
V.I.【模板】原根
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1000000;
int T,n,d,pri[1001000],phi[1001000],mnp[1001000];
int ksm(int x,int y){
int z=1;
for(;y;y>>=1,x=1ll*x*x%n)if(y&1)z=1ll*z*x%n;
return z;
}
void sieve(){
for(int i=2;i<=N;i++){
if(!pri[i])pri[++pri[0]]=i,phi[i]=i-1,mnp[i]=i;
for(int j=1;j<=pri[0]&&i*pri[j]<=N;j++){
pri[i*pri[j]]=true,mnp[i*pri[j]]=pri[j];
if(i%pri[j])phi[i*pri[j]]=phi[i]*phi[pri[j]];
else{phi[i*pri[j]]=phi[i]*pri[j];break;}
}
}
}
vector<int>factorize(int ip){
vector<int>ret;
while(ip!=1)ret.push_back(mnp[ip]),ip/=mnp[ip];
sort(ret.begin(),ret.end()),ret.resize(unique(ret.begin(),ret.end())-ret.begin());
return ret;
}
bool checkrootexist(int ip){
if(n==2||n==4)return true;
vector<int>v=factorize(ip);
if(v.size()==1&&v[0]!=2)return true;
if(ip&1)return false;
v=factorize(ip/2);
return v.size()==1&&v[0]!=2;
}
vector<int>fp;
bool checkisroot(int ip){
for(auto i:fp)if(ksm(ip,phi[n]/i)==1)return false;
return true;
}
vector<int>res;
void findallroots(int ip){
for(int i=1;i<=phi[n];i++)if(__gcd(i,phi[n])==1)res.push_back(ksm(ip,i));
sort(res.begin(),res.end());
}
int main(){
sieve();
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&d),res.clear();
if(!checkrootexist(n)){puts("0\n");continue;}
fp=factorize(phi[n]);
for(int i=1;;i++)if(__gcd(i,n)==1&&checkisroot(i)){findallroots(i);break;}
printf("%d\n",res.size());
for(int i=d-1;i<res.size();i+=d)printf("%d ",res[i]);puts("");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?