阶和原根
阶
整数的阶:给定\(a\),求使得\(a^x \equiv 1 \pmod p\)成立的最小的正整数\(x\),这个\(x\)称为\(a\)模\(p\)下的阶,记作\(\text{ord}_pa\),显然要满足\((a,p)=1\)。由欧拉定理易知它肯定存在,且能得到\(\text{ord}_pa \mid \varphi(p)\)。
阶的性质:
1、\(\text{ord}_pa \mid \varphi(p)\)。
2、\(a\),\(a^2\),\(a^3\dotsb a^{\text{ord}_pa}\)在模\(p\)意义下互不相等。显然如果相等会违背阶的定义。
3、\(a^r \equiv a^{r'} \pmod p \Leftrightarrow r \equiv r' \pmod{\text{ord}_pa}\)。同样很显然。
4、\(\text{ord}_ma^k=\frac{\text{ord}_ma}{(\text{ord}_ma,k)}\)。证明用一下裴蜀定理即可。
5、\(\text{ord}_m(ab) = \text{ord}_ma \times \text{ord}_mb \Leftrightarrow (\text{ord}_ma, \text{ord}_mb) = 1\)。用整除和阶的性质证一证即可。这表明阶是积性函数。
如何求\(\text{ord}_pa\)?枚举\(\varphi(p)\)的质因子试除判断即可。
std::vector<int> fac; // 存储分解的质因子
void getfac(int N) {
fac.clear();
rep(i, 1, p[0]) if (N > 1 && check[N]) {
if (N % p[i]) break;
fac.push_back(p[i]);
while (!(N % p[i])) N /= p[i];
}
if (N > 1) fac.push_back(N);
}
int ord(int n) { // 前提(n,P)=1
int r = phi[P]; getfac(r); // 分解质因子
rep0(i, fac.size()) while (!(r % fac[i]) && qpow(n, r/fac[i]) == 1) r /= fac[i]; // 不断试除
return r; // 答案
}
原根
原根:若\(\text{ord}_pa=\varphi(p)\)时,则称\(a\)是\(p\)的原根。
有原根的数为\(1\),\(2\),\(4\),\(t\),\(2t\),\(t^k\),\(2t^k\),其中\(t\)为奇素数,\(k \in \Z_+\)。
由此我们可以看出:原根\(g\)的\(t\)次方在模\(p\)意义下会遍历所有\(\varphi(p)\)个与\(p\)互质的数。
如果在模数\(p\)下有原根,则原根的个数为\(\varphi(\varphi(p))\)。
\(Proof\):
通过这个还可以证在缩系中,如果\(d \mid \varphi(p)\),则恰有\(\varphi(d)\)个数的阶为\(d\),这里不证了(同上)。
判断\(a\)是否为原根?用定义。
如何求原根?原根比较多,且相对分布均匀,所以直接暴力找。