求原根(模板)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yz467796454/article/details/82014633

数论令人头秃,原理就看看别人博客吧:数论之原根

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include <sstream>
#include <set>
#include <queue>
#include <stack>
#include <map>
#include <bitset>
using namespace std;
typedef long long  LL;
const int inf=0x3f3f3f3f;
const double pi= acos(-1.0);
const double esp=1e-7;
const int Maxn=1e6+10;
int prime[Maxn];//存储素数
int sprime[Maxn];//存储P-1的素因子
bitset<Maxn>pri;//结果只有0和1,判断是否为素数
int k;//记录Maxn以内的素数个数
int cnt;//记录素因子的个数
void is_prime()
{
    pri.set();//将所有的二进制数都标为1
    for(int i=2; i<Maxn; i++) {
        if(pri[i]) {
            prime[k++]=i;
            for(int j=i+i; j<Maxn; j+=i)
                pri[j]=0;
        }
    }
}
void Divide(int n)//将n分解为素因子
{
    cnt=0;
    int t=(int)sqrt(1.0*n);
    for(int i=0; prime[i]<=t; i++) {
        if(n%prime[i]==0) {
            sprime[cnt++]=prime[i];
            while(n%prime[i]==0)//因为有可能有多个peime[i]
                n/=prime[i];
        }
    }
    if(n>1)
        sprime[cnt++]=n;//可能只有自己一个素因子
}
LL modexp(LL a,LL b,int mod)//快速幂取余
{
    LL res=1;
    while(b>0) {
        a=a%mod;
        if(b&1)
            res=res*a%mod;
        b=b>>1;
        a=a*a%mod;
    }
    return res;
}
 
int main(){
    int p;
    is_prime();
    while(~scanf("%d",&p)) {
        Divide(p-1);
        for(int g=2; g<p; g++) {
            int flag=1;
            for(int i=0; i<cnt; i++) {
                int t=(p-1)/sprime[i];
                if(modexp(g,t,p)==1) {
                    flag=0;
                    break;
                }
            }
            if(flag) {
                int root=g;
                printf("%d\n",root);
                break;
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yz467796454/article/details/82014633