【数学】原根
一个数有原根时,有 个原根。
有原根的充要条件是, 其中p是奇质数。
求一个最小的原根,从 枚举到 ,然后若 并且对于 的所有质因数 ,都有 ,那么i就是最小的原根。
找到一个最小的原根之后,可以通过这个最小的原根找到其他的原根。
设最小的原根为 那么,从 遍历到 ,假如 那么,也是 一个原根。
多次求原根
1、预处理出所需范围内的质数、质数幂、欧拉函数,
2、给出要求原根的数 ,判断 是否有原根,若没有则返回,
3、求出 ,并对 分解质因数,
4、从 开始暴力枚举,根据伯吉斯的证明,最坏情况下枚举到 会得到第一个原根,
5、用第一个原根求出其他所有的原根
时间复杂度
验证:https://www.luogu.com.cn/problem/P6091
copyconst int MAXN = 1e6 + 5;
int p[MAXN], ptop;
int pm[MAXN], pk[MAXN];
int phi[MAXN];
void sieve(int n) {
pm[1] = 1, pk[1] = 1;
phi[1] = 1;
for(int i = 2; i <= n; ++i) {
if(!pm[i]) {
p[++ptop] = i, pm[i] = i, pk[i] = i;
phi[i] = i - 1;
}
for(int j = 1; j <= ptop; ++j) {
int t = i * p[j];
if(t > n)
break;
pm[t] = p[j];
if(i % p[j]) {
pk[t] = pk[p[j]];
phi[t] = phi[i] * phi[p[j]];
} else {
pk[t] = pk[i] * p[j];
if(pk[t] == t)
phi[t] = t - t / p[j];
else
phi[t] = phi[t / pk[t]] * phi[pk[t]];
break;
}
}
}
}
int qpow(ll x, int n, int mod) {
ll res = 1;
while(n) {
if(n & 1)
res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res;
}
vi getPrimeFactors(int n) {
vi res;
for(int i = 1; p[i]*p[i] <= n; ++i) {
if(n % p[i] == 0) {
res.eb(p[i]);
while(n % p[i] == 0)
n /= p[i];
}
}
if(n > 1)
res.eb(n);
return res;
}
int getMinPrimitiveRoot(int n) {
if(!(n == 2 || n == 4 || pk[n] == n || (n % 2 == 0 && pk[n / 2] == n / 2)))
return -1;
vi pfs = getPrimeFactors(phi[n]);
for(int i = 1;; ++i) {
if(qpow(i, phi[n], n) == 1) {
bool ok = 1;
for(const int &pf : pfs) {
if(qpow(i, phi[n] / pf, n) == 1) {
ok = 0;
break;
}
}
if(ok)
return i;
}
}
exit(-1);
}
vi getAllPrimitiveRoot(int n) {
vi res;
int g = getMinPrimitiveRoot(n);
if(g != -1) {
res.reserve(phi[n]);
for(int i = 1; i <= phi[n]; ++i) {
if(__gcd(i, phi[n]) == 1)
res.eb(qpow(g, i, n));
}
srt(res);
}
return res;
}
上面这个算法可以找到所有的原根,复杂度爆炸。
找一个最小的原根非常快,先判断是否存在原根,通过质因数分解判断,然后用质因数分解求出欧拉函数,再对欧拉函数进行质因数分解,然后套一堆快速幂。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下