zoukankan      html  css  js  c++  java
  • 原根定义

    先引入一个概念:阶。

    设a和n是互素的整数,a≠0,n>0  使得ax≡1(mod n),x的最小整数就是a模n的阶,而当x=phi(n)时,称a为n的原根

    对于求出原根的好处:可以利用 [1,n-1]->i 求出的所有 ai (mod n)为一个[1,n-1]中的整数只出现一次的序列。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=1e9+7;
    
    ll gcd(ll a,ll b)
    {
        return b?gcd(b,a%b):a;
    }
    
    ll fpow(ll a,ll n,ll p)
    {
        ll sum=1,base=a%p;
        while(n!=0)
        {
            if(n%2)sum=sum*base%p;
            base=base*base%p;
            n/=2;
        }
        return sum;
    }
    
    vector<ll> getPrimFac(ll n)
    {
        vector<ll>fac;
        fac.clear();
        for(ll i=2;i*i<=n;i++)
        {
            if(n%i==0)
            {
                fac.push_back(i);
                while(n%i==0)n/=i;
            }
        }
        if(n>1)fac.push_back(n);
        return fac;
    }
    
    bool hasRoot(ll n)
    {
        if(n==2||n==4)return true;
        if(n<=1||n%4==0)return false;
        ll num=0;
        while(n%2==0)n/=2;
        for(ll i=3;i*i<=n;i++)
        {
            if(n%i==0)
            {
                num++;
                while(n%i==0)n/=i;
            }
        }
        if(n>1)num++;
        if(num==1)return true;
        return false;
    }
    
    ll getPhi(ll n)
    {
        ll ans=n;
        for(ll i=2;i*i<=n;i++)
        {
            if(n%i==0)
            {
                ans=ans/i*(i-1);
                while(n%i==0)n/=i;
            }
        }
        if(n>1)ans=ans/n*(n-1);
        return ans;
    }
    
    ll getRoot(ll n)
    {
        if(!hasRoot(n))return -1;//不存在原根返回-1
        if(n==2)return 1;
        if(n==3)return 2;
        if(n==4)return 3;
        ll w=getPhi(n);
        vector<ll>fac=getPrimFac(w);
        for(ll i=2;i<w;i++)
        {
            if(gcd(i,n)!=1)continue;
            ll is=1;
            for(ll j=0;j<fac.size();j++)
            {
                if(fpow(i,w/fac[j],n)==1)is=0;
            }
            if(is)return i;
        }
        return -1;
    }
    
    int main()
    {
        ll p;
        scanf("%lld",&p);
        printf("%lld
    ",getRoot(p));
        return 0;
    }
    模板求p的原根
  • 相关阅读:
    jQuery 全选-------左右移动select
    圆饼 折线图的 js
    折线图
    圆饼图
    el 表达式的if else
    list查询出来后存到map里
    spring Mvc 二级联动(3)
    Python之列表
    SAS 中的数据拼接
    Git 安装不是默认路径,生成密钥
  • 原文地址:https://www.cnblogs.com/starve/p/12977181.html
Copyright © 2011-2022 走看看