zoukankan      html  css  js  c++  java
  • 【HDU 4992】 Primitive Roots (原根)

     

    Description

    We say that integer x, 0 < x < n, is a primitive root modulo n if and only if the minimum positive integer y which makes x y = 1 (mod n) true is φ(n) .Here φ(n) is an arithmetic function that counts the totatives of n, that is, the positive integers less than or equal to n that are relatively prime to n. Write a program which given any positive integer n( 2 <= n < 1000000) outputs all primitive roots of n in ascending order.

    Input

    Multi test cases. 
    Each line of the input contains a positive integer n. Input is terminated by the end-of-file seperator.

    Output

    For each n, outputs all primitive roots of n in ascending order in a single line, if there is no primitive root for n just print -1 in a single line.

    Sample Input

    4
    25

    Sample Output

    3
    2 3 8 12 13 17 22 23
     
    【题意】
      求n的所有原根,若没有就输出-1(n<=10^6)
     
    【分析】
      

    求出n的所有原根,不存在原根输出-1。

    原根的定义题目已经给出,对于n的原根x,则满足x的y次幂模n等于1的最小y是n的欧拉函数值phi(n),也就是小于等于n且与n互质的个数。

    官方的题解里面说暴力求出一个原根来,然后利用结论:

    如果g是模m的原根,整数d>=0,则g的d次幂是模m的原根的一个充要条件是d和phi(m)互质。

    d暴力枚举:

    一个是如果gcd(g, m)=1,且g^d=1(mod m),则d为phi(m)的一个因子。换句话说如果g是m的原根,那么对于phi(m)的所有因子d(不包含phi(m)本身),g^d=1(mod m)是不成立的。我们可以通过枚举phi(m)的质因子以及g^phi(m)=1(mod m)是否成立来判断g是否是模m的原根。

    然后有些不存在原根的数字利用另一条性质排除:

    模m有原根的充要条件是m=2,4,p^n, 2p^n,p为奇质数,n任意正整数。

    如果m没有满足上述条件,就直接输出-1。

    http://blog.csdn.net/hongrock/article/details/39179291

    
    

     代码如下:

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 #include<cmath>
      8 using namespace std;
      9 #define LL long long
     10 #define Maxn 1000010
     11 
     12 int phi[Maxn],pri[Maxn],pl;
     13 bool q[Maxn],qs[Maxn];
     14 
     15 int gcd(int a,int b)
     16 {
     17     if(b==0) return a;
     18     return gcd(b,a%b);
     19 }
     20 
     21 void get_phi(int mx)
     22 {
     23     pl=0;
     24     memset(q,1,sizeof(q));
     25     memset(qs,0,sizeof(qs));
     26     phi[1]=1;
     27     for(int i=2;i<=mx;i++)
     28     {
     29         if(q[i]) pri[++pl]=i,qs[i]=i==2?0:1,phi[i]=i-1;
     30         for(int j=1;j<=pl;j++)
     31         {
     32             if(i*pri[j]>mx) break;
     33             q[i*pri[j]]=0;
     34             if(i%pri[j]==0)
     35             {
     36                 phi[i*pri[j]]=phi[i]*pri[j];
     37                 if(qs[i]) qs[i*pri[j]]=1;
     38             }
     39             else phi[i*pri[j]]=phi[i]*(pri[j]-1);
     40             if(i%pri[j]==0) break;
     41         }
     42     }
     43     for(int i=mx/2;i>=1;i--) if(qs[i]) qs[2*i]=1;
     44     qs[2]=1;qs[4]=1;
     45 }
     46 
     47 int qpow(int x,int y,int p)
     48 {
     49     LL ans=1,xx=x,pp=p;
     50     while(y)
     51     {
     52         if(y&1) ans=(ans*xx)%pp;
     53         xx=(xx*xx)%pp;
     54         y>>=1;
     55     }
     56     return (int)ans;
     57 }
     58 
     59 int np[Maxn],nl;
     60 void div(int x)
     61 {
     62     nl=0;
     63     for(int i=1;pri[i]*pri[i]<=x;i++) if(x%pri[i]==0)
     64     {
     65         np[++nl]=pri[i];
     66         while(x%pri[i]==0) x/=pri[i];
     67     }
     68     if(x>1) np[++nl]=x;
     69 }
     70 
     71 int ffind(int n)
     72 {
     73     div(phi[n]);
     74     for(int i=2;i<=n;i++)
     75     {
     76         if(qpow(i,phi[n],n)!=1) continue;
     77         bool ok=1;
     78         for(int j=1;j<=nl;j++)
     79         {
     80             if(qpow(i,phi[n]/np[j],n)==1) {ok=0;break;}
     81         }
     82         if(!ok) continue;
     83         return i;
     84     }
     85     return -1;
     86 }
     87 
     88 int op[Maxn];
     89 
     90 void output(int g,int n)
     91 {
     92     op[0]=0;
     93     op[++op[0]]=g;
     94     LL M=(LL)n,now=(LL)g,gg=(LL)g;
     95     for(int i=2;i<phi[n];i++)
     96     {
     97         now=(now*gg)%M;
     98         if(gcd(i,phi[n])==1) op[++op[0]]=(int)now;
     99     }
    100 }
    101 
    102 int main()
    103 {
    104     get_phi(1000000);
    105     int n;
    106     while(scanf("%d",&n)!=EOF)
    107     {
    108         if(!qs[n]) {printf("-1
    ");continue;}
    109         int g=ffind(n);
    110         output(g,n);
    111         sort(op+1,op+op[0]+1);
    112         for(int i=1;i<=op[0];i++) printf("%d ",op[i]);
    113         printf("
    ");
    114     }
    115     return 0;
    116 }
    [HDU 4992]

    2016-09-06 16:39:31

  • 相关阅读:
    poj1006 Biorhythms ——中国剩余定理入门题
    hoj12614 Dictionary ——拓扑排序找环&&比赛残留题
    2013年4月23日 雨
    zoj1586 QS Network ——最小生成树入门题_Prim算法
    hoj12616 Median Tree ——最小生成树入门题&&比赛残留题_Kruscal算法
    tset3
    testhtml
    Oracle SQLID 与 Hash_value 算法及转换
    Linux 脚本中生成日志 set x
    test wrod
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/5846278.html
Copyright © 2011-2022 走看看