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;
        }
    }
}

 

猜你喜欢

转载自www.cnblogs.com/8023spz/p/10014819.html