1. 程式人生 > >51nod 1135 原根

51nod 1135 原根

設m是正整數,a是整數,若a模m的階等於φ(m),則稱a為模m的一個原根。(其中φ(m)表示m的尤拉函式) 給出1個質數P,找出P最小的原根。  

輸入

輸入1個質數P(3 <= P <= 10^9)

輸出

輸出P最小的原根。

輸入樣例

3

輸出樣例

2
問題給出了原根的定義,對於質數p,他的尤拉函式值是p-1,還需要知道這裡的階的定義:
設m>1,gcd(a,m)=1,a^r≡1(mod m)的最小的r就是a對模m的階。
具體怎麼求,一般方法是列舉a從2開始,然後列舉r∈[2,φ(m)),如果都不滿足a^r≡1(mod m),那麼說明a滿足,但是過於暴力,
更簡單的是,設φ(m)=p1^q1*p2^q2*...*pn^qn,直接判斷a^(φ(m)/pi)≠1(mod m)(i∈[1,n])恆成立即可。
程式碼:
#include <iostream>
#include <cstdio>
#define MAX 100000

using namespace std;
typedef long long ll;
ll p;
int c,flag;
ll s[MAX];
void getp(int x) {
    for(int i = 2;i * i <= x;i ++) {
        if(x % i == 0) {
            s[c ++] = i;
            while(x && x % i == 0
) { x /= i; } } } if(x) s[c ++] = x; } ll pow_p(ll a,ll b) {///a^b mod p ll d = 1; while(b) { if(b % 2) d = (d * a) % p; a = (a * a) % p; b /= 2; } return d; } int main() { scanf("%lld",&p); getp(p
- 1);///獲取質因子 for(int i = 2;i < p;i ++) { for(int j = 0;j < c;j ++) { if(pow_p(i,(p - 1) / s[j]) == 1) { flag = 1; break; } } if(flag) flag = 0; else { printf("%d",i); break; } } }