原根的求解證明 附程式碼
求解方法:
列舉
從2開始列舉,然後暴力判斷g^(P-1) = 1 (mod P)是否當且當指數為P-1的時候第一次成立
而由於原根一般都不大大多都在200以內,所以可以暴力得到.
方法
例如求任何一個質數x的任何一個原根,一般就是列舉2到x-1,並檢驗。有一個方便的方法就是,求出x-1所有不同的質因子p1,p2…pm,對於任何2<=a<=x-1,判定a是否為x的原根,只需要檢驗a^((x-1)/p1),a^((x-1)/p2),…a^((x-1)/pm)這m個數中,是否存在一個數mod x為1,若存在,a不是x的原根,否則就是x的原根。
原來的複雜度是O(P-1),現在變成O(m)*log(P-1)m為x-1質因子的個數。質因子的個數也是log級別的。
證明
若存在,那麼顯然不是原根。
否則,假設存在一個最小的t < phi(x)=x-1使得a^t = 1 (mod x)
那麼t一定整除於x-1。
為什麼呢?我們假設t不整除於x-1,那麼因為t < x-1,所以一定能得到一組k,p,使得x-1 = k * t+p。因為a^t = 1 (mod x),所以a^(k * t) = 1 (mod x),又因為a^(x-1) = 1 (mod x),所以a^p = 1 (mod x),而p < t 所以t不是最小的,矛盾。
所以那麼t一定整除於x-1。所以我們只需要判斷x-1的所有因數就行了。我們考慮,t一定是比x-1少一些質因子。而如果a^t = 1 (mod x) 則a^(k*t) = 1 (mod x)。所以我們分解x-1的質因數只要a^((x-1)/pi )!=1(mod x)那麼所有不包含pi這個質因子的t就不滿足a^t = 1 (mod x) 。遍歷一遍pi就排除了所有的t。
void divi(int n){//分解質因數
top = 0;
for(register int i=1; prim[i]*prim[i]<=n; i++)
if(n % prim[i] == 0){
num[++top] = prim[i];
while(n % prim[i] == 0) n /= prim[i];
}
if(n != 1) num[++top] = n;//
}
int root(int p){//求原根 (階=phi(mod))
divi(p - 1);
for(int g=1; ; g++){//列舉原根
bool flag = true;
for(int i=1; i<=top; i++){
int goal = (p-1) / num[i];
if(mpow(g, goal, p) == 1) {//check
flag = false; break;
}
}
if(flag) return g;
}
return -1;
}