zoukankan      html  css  js  c++  java
  • hdu 4992 Primitive Roots 【求原根模板】

    题目链接

    大题流程: 判定是否有原根->求出最小原根->利用最小原根找出全部原根

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int maxn=1e6+5;
    int prime[maxn+5];
    bool check[maxn+5];
    int phi[maxn+5];
    int num_prime;
    void init()
    {
        memset(check, false, sizeof(check));
        phi[1]=1;
        for(int i=2; i<=maxn; i++)
        {
            if(!check[i])
            {
                prime[num_prime++]=i;
                phi[i]=i-1;
            }
            for(int j=0; j<num_prime; j++)
            {
                if(i*prime[j]>maxn) break;
                check[i*prime[j]]=true;
                if(i%prime[j]==0)
                {
                    phi[i*prime[j]]=phi[i]*prime[j];
                    break;
                }
                else
                {
                    phi[i*prime[j]]=phi[i]*(prime[j]-1);
                }
            }
        }
    }
    
    LL gcd(LL a, LL b)
    {
        return b? gcd(b,a%b):a;
    }
    
    void get(LL n,vector<LL>& fac)    //对n进行因式分解 
    {
        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);
    }
    
    LL qpow(LL x,LL n,LL mod)        //求x^n%mod
    {
        LL ret=1;
        for(; n; n>>=1)
        {
            if(n&1) ret=ret*x%mod;
            x=x*x%mod;
        }
        return ret;
    }
    
    vector<LL> fac;
    vector<LL> ans;
    
    bool ok(LL x)
    {
        if(x%2==0) x/=2;
        if(x%2==0) return false;
        for(int i=0; prime[i]*prime[i]<=x; i++) if(x%prime[i]==0)
            {
                while(x%prime[i]==0) x/=prime[i];
                return x==1;
            }
        return true;
    }
    
    LL get_g(LL p)        //得到一个正整数p的最小原根 
    {
        for(int i=2; i<p; i++)
        {
            bool flag=false;
            for(LL x:fac)
                if(qpow(i,phi[p]/x,p)==1)
                {
                    flag=true;
                    break;
                }
            if(!flag&&qpow(i,phi[p],p)==1)  return i;
        }
    }
    
    void GetAns(LL g,LL p,vector<LL>& ans)    //由最小原根p,得到某正整数p的全部原根 
    {
        ans.clear();
        ans.push_back(g);
        for(int i=2; i<phi[p]; i++)
            if(gcd(i,phi[p])==1) ans.push_back(qpow(g,i,p));
    }
    
    int main()
    {
        init();
        LL p;
        while(~scanf("%lld",&p))
        {
            if(p==2||p==4)
            {
                printf("%lld
    ",p-1);
                continue;
            }
            if(!ok(p))        //首先判断是否有原根 
            {
                puts("-1");
                continue;
            }
            get(phi[p],fac);
            LL g=get_g(p);        //定义g为最小原根
            GetAns(g,p,ans);
            sort(ans.begin(),ans.end());
            for(int i=0; i<ans.size(); i++)
                printf("%lld%c",ans[i],i==ans.size()-1? '
    ':' ');
        }
    }
  • 相关阅读:
    PAT甲级1060 Are They Equal【模拟】
    PAT甲级1131 Subway Map【dfs】【输出方案】
    PAT甲级1052 Linked List Sorting
    Dev的GridControl控件选择框的使用
    关于MongoDB数据库中文件唯一性的问题
    docker-学习笔记5-存储卷
    docker-学习笔记4-网络
    docker-学习笔记3-镜像基础
    docker-学习笔记2-基础用法
    docker-学习笔记1-基础入门
  • 原文地址:https://www.cnblogs.com/Just--Do--It/p/7382593.html
Copyright © 2011-2022 走看看