原根
为什么要写这个呢?因为给 FFT 和 NTT 做铺垫。
阶
想学习原根,就要学习一下阶。
阶的定义:如果 \(a^n\equiv 1\pmod m\),那么我们就说 \(n\) 是 \(m\) 的阶,记为 \(n=\delta_m(a)\)。
我们来说说阶的好的性质。
第一个性质:\(a,a^2,a^3,...a^{\delta_m(a)}\) 两两对 \(m\) 取模不相同。
简单证明:设存在 \(i,j\in[1,\delta_m(a)]\),使得 \(a^i\equiv a^j\pmod m\),那么 \(a^{|i-j|}\equiv 1\pmod m\)。
但是这样 \(|i-j|< \delta_m(a)\)。所以反证失败。
第二个性质:\(a^n\equiv 1\pmod m\),则 \(\delta(m)|n\)。
这个结论更唐,不想证了。
第三个性质:\(m\in \mathbb{N}^+,a,b\in\mathbb{Z},(a,m)=(b,m)=1\),则
的充要条件是
证明考虑用前两个性质即可,比较简单,不再赘述。
第四个性质:对于 \(k\in\mathbb{N},m\in\mathbb{N}^+,a\in\mathbb{Z},(a,m)=1\),则
证明:
我们可以注意到
那么我们只需要证明他们相等即可。
我们考虑 \(a^{\delta_m(a)}\equiv 1\pmod m\),而
所以我们就发现
非常好,这样我们就证明了如上的结论!
说完阶,我们终于可以说说原根了。
原根
原根的定义:设 \(m\in \mathbb{N}^+\),\(g\in Z\),若 \((g,m)=1\),且 \(\delta_m(a)=\varphi (m)\),那么我们称 \(g\) 表示 \(m\) 的原根。
那么我们可以说 \(g,g^2,g^3,\cdots,g^{\varphi(m)}\) 模 \(m\) 互不相同,这就叫做 \(m\) 的简化剩余系。
原根的判定定理
设 \(m\ge 3,(g,m)=1\),则 \(g\) 是 \(m\) 的原根的充要条件是,对于 \(\varphi(m)\) 的每一个素数因子 \(p\),都有 \(g^{\frac{\varphi(m)}{p}}\not\equiv 1\pmod m\)。
必要性很显然,我们考虑反证法证明充要性。
我们考虑假设存在 \(g^{\frac{\varphi(m)}{p}}\not\equiv 1\pmod m\),而 \(g\) 不是原根。那么我们将 \(g^{\varphi(m)}\equiv 1\pmod m\) 带入阶的性质2。
我们可以得到 \(\delta_m(g)<\varphi(m)\),且 \(\delta_m(g)\mid \varphi m\)。
那么存在素数因子 \(p\),使得 \(\delta_m(g)\mid \frac{\varphi(m)}{p}\)。
则 \(g^{\frac{\varphi(m)}{p}}\equiv 1\pmod m\),矛盾!所以反证法证明原命题成立。
原根个数
若一个数 \(m\) 有原根 \(g\),那么对于任意的 \(\varphi(m)\) 的因子 \(d\),模 \(m\) 的原根个数为 \(\varphi(d)\) 个。
特别的,\(m\) 的原根个数为 \(\varphi(\varphi(m))\) 个。
我们考虑简单的证明。设 \(d'=\frac{\varphi(m)}{d}\),那么 \(\delta_m(g^{d'})=\frac{\delta_m(g)}{(\delta_m(g),d'}=d\),因此 \(g\) 模 \(m\) 的 \(d\) 阶元素存在。
设 \(a=g^{d'}\),\(k\) 是不大于 \(d\) 的整数,由阶的性质 \(a,a^2,\cdots,a^d\) 互不相同,且 \(\delta_m(a^k)=\frac{\delta_m(a)}{(\delta_m(a),k)}\)。
当且仅当 \((d,k)=1\) 时,\(\delta_m(a^k)=d\)。这样的 \(k\) 显然不少于 \(\varphi(d)\)。
而我们发现 \(\varphi(m)=\sum_{d|\varphi(m)}\varphi(d)\),则模 \(m\) 的 \(d\) 阶就恰好有 \(\varphi(d)\)。
原根存在定理
一个数 \(m\) 存在原根当且仅当 \(m=2,4,p^{\alpha},2p^{\alpha}\),其中 \(p\) 为奇素数,\(\alpha\in \mathbb{N}^+\)。
具体证明………………太难了,等博主学会了再说吧。主要是因为太多 latex 了……
具体可以参考 这里。
现在你会了原根,那么怎么才能找到所有的原根呢?
我们来看 原根模板题。
首先我们通过原根存在定理判断是否存在原根。
如果存在原根,我们应该如何找到所有的原根呢?
我们根据阶的性质,我们发现只要求出模 \(n\) 最小的原根 \(g\),那么其他的原根都是 \(g^k\)。
如何才能找到 \(g\) 呢?
首先,最小的原根应该比较小,因为模 \(m\) 的原根有 \(\varphi(\varphi(m))\) 个,然后根据原根判定定理可以轻松判断最小原根。判断原根的方法参考原根判断定理。这个复杂度是很小的。
那么怎么才能找到所有的原根呢?
我们只需要去枚举 \(d\),使得 \((d,\varphi(n))=1\),那么 \(g^d\) 即为一个原根。这个证明很简单,就是 \(\delta_m(g^d)=\frac{\delta_n(g)}{(\delta_n(g),d}\)。那么如果 \((\delta_n(g),d)\neq 1\),那么 \(\delta_m(g^d)<\delta_n(g)=\varphi(n)\)。
然后这道题就做完了。
总的时间复杂度应该是 \(\mathcal O(\sqrt[4]{n}\log n)\),具体证明我不会。
还有一道原根性质应用题ABC212G。
这道题我们可以进行一些化简。
我们知道,对于 \(g^0,g^1,\cdots,g^{P-2}\) 原根互不相同,随意我们可以用 \(g^1,g^2,\cdots,g^{P-1}\) 来代替 \(P\),即设 \(x=g^a,y=g^b\),那么:
由裴蜀定理可以知道,当且仅当 \(\gcd(a,P-1)\mid b\),那么:
以上式子可以 \(\mathcal O(\sqrt{n}\log n)\) 解决。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=998244353;
int P;
int PHI(int x)
{
int ans=x;
for(int i=2;i*i<=x;i++)
{
if(x%i) continue;
ans=ans/i*(i-1);
while(x%i==0) x/=i;
}
if(x>1) ans=ans/x*(x-1);
return ans%MOD;
}
signed main()
{
cin>>P;P--;int ans=1;
for(int i=1;i*i<=P;i++)
{
if(P%i) continue;
ans=(ans+PHI(i)*i%MOD)%MOD;
if(i*i!=P) ans=(ans+PHI(P/i)*((P/i)%MOD)%MOD)%MOD;
}
cout<<ans;
return 0;
}

浙公网安备 33010602011771号