階:設a,p是整數,a和p互素,那么:使
成立的最小正整數n叫做a模p的階.

原根:設m是正整數,a是整數,若a mod m的階等於φ(m),則稱a為模m的一個原根.(其中φ(m)表示m的歐拉函數)
假設一個數g是質數P的原根,那么
的結果兩兩不同,且有 1<g<P,0<i<P,歸根到底就是
當且僅當指數為P-1的時候成立.


有了這個上面性質,就可以容易的求出質數P的原根了.
Step1 將P-1進行質因數分解

Step2 枚舉i,並判斷對於每個i是否都有
(可以應用快速冪)

第一個符合條件的i就是P的最小原根
對於合數,只要將Step2中的p-1替換成φ(p)即可.
這里是代碼
#include <cmath> #include <cstdio> #define ll long long #define maxn 1000010 bool vis[maxn]; ll p,prime[maxn],cnt; ll fp(ll x,ll a){ ll ret=1; for(x%=p;a;a>>=1,x=x*x%p) if(a&1) ret=ret*x%p; return ret; } void get_prime(int x){//篩出x以內的素數 for(int i=2;i<=x;i++){ if(!vis[i]) prime[++cnt]=i; for(int j=1;j<=cnt;j++){ if(i*prime[j]>x) break; vis[i*prime[j]]=1; if(i%prime[j]==0) break; } } } bool check(ll x){//檢查x是否是p的原根 ll t=sqrt(x)+10; for(int i=1;prime[i]<=t;i++){ if((p-1)%prime[i]==0&&fp(x,(p-1)/prime[i])%p==1) return 0; } return 1; } int main(){ scanf("%lld",&p); get_prime(maxn); for(int i=1;i<=1000000;i++){ if(check(i)){ printf("%d\n",i); return 0; } } }