51 nod 1135原根

来源:互联网 发布:html5网游源码 编辑:程序博客网 时间:2024/06/07 03:05


51 nod  1135原根






题意: a 模 m 的阶定义: gcd(a,m)=1,使得这里写图片描述成立的最小的 r,称为 a 对 模m 的 阶

  那么整个题就是要求  a^(p-1) % p==1 成立的 最小  a ;


方法:  copy   by  点击打开链接

分解质因子,

对任何整数 a ∈[1,p-1], 检验 a 是否为 p 的原根,

检验方法:a^((p-1)/p1),a^((p-1)/p2),...a^((p-1)/pm) 中是否存在一个 模p 等于 1 ,

存在的话 a 就不是 模p 的一个原根(即p-1就不是a对模p的阶),否则a就为原根。


#include<bits/stdc++.h>using namespace std;int pri[50010];bool vis[50010];int A[50010];int len1,len2;typedef long long ll;void init(){    memset(vis,false,sizeof vis);    len1=0;    for(int i=2;i<50010;i++)    {        if(!vis[i])            pri[len1++]=i;        for(int j=0;j<len1&&i*pri[j]<50010;j++)        {            vis[i*pri[j]]=1;            if(i%pri[j]==0)                break;        }    }}bool Pow(ll a,ll m,ll mod){    ll ans=1;    a=a%mod;    while(m)    {        if(m&1)            ans=ans*a%mod;        a=a*a%mod;        m>>=1;    }    if(ans==1)        return 1;    return 0;}void Div(int m){    len2=0;    for(int i=0;i<len1;i++)    {        if(m%pri[i]==0)        {            A[len2++]=pri[i];            while(m%pri[i]==0)                m/=pri[i];        }    }    if(m>1)        A[len2++]=m;}int main(){    int p;    init();    while(scanf("%d",&p)!=EOF)    {        Div(p-1);        int fla;        for(int a=2;a<p;a++)        {            fla=1;            for(int j=0;j<len2;j++)            {              //  cout<<" DIv: "<<A[j]<<endl;                int x=(p-1)/A[j];                if(Pow(a,x,p))                {                    fla=0;                    break;                }            }            if(fla)            {                cout<<a<<endl;                break;            }        }        //cout<<"-1"<<endl;    }    return 0;}

原创粉丝点击