• HDU4992 求所有原根


    Primitive Roots

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 583    Accepted Submission(s): 144

    Problem 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 xy = 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,xk≡1(mod n)的最小正整数k是φ(n),那么就称x是n的原根。
    题目里面也讲了。φ(n)就是欧拉函数。
    原根有很多美丽的性质。比如说:
    1. 有原根的数只有2,4,p^n,2p^n(p为质数,n为正整数)。
    2. 一个数的最小原根的大小是O(n0.25)的。
    3. 如果g为n的原根,则gd为n的原根的充要条件是(d,φ(n))=1;
    4. 如果n有原根,它的原根个数为φ(φ(n))。

    那么来看一下这道题:

    首先根据性质1,我们可以通过预处理质数,把不存在的情况判掉。

    然后根据性质3,找到一个原根后枚举次方判gcd就可以了。

    怎么找到一个原根呢?按照性质2傻傻去跑在这种多组数据的题目里是肯定不行的。

    那么有一个喜大普奔的结论来帮助我们:

    因为gφ(n)≡1(mod n),而对于比φ(n)小的数都不成立。

    枚举φ(n)的质因子p,看gφ(n)/p在模意义下是否是1。

    是1的话g就不是原根。

    证明起来有点麻烦,这里就不写了。

    所以找原根大概是O(n0.25/2)的。

    找到之后枚举次方就可以了,因为是充分条件。

    想剪个好枝却剪烂的某人在HDU上留下了5个WA... ...

    #include    <iostream>
    #include    <cstdio>
    #include    <cstdlib>
    #include    <algorithm>
    #include    <vector>
    #include    <cstring>
    #include    <queue>
    #define LL long long int
    #define ls (x << 1)
    #define rs (x << 1 | 1)
    #define MID int mid=(l+r)>>1
    using namespace std;
    
    const int N = 1000000+10;
    int P[N],vis[N],phi[N],tot,n;
    
    inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
    
    inline void prepare()
    {
      phi[1]=1;
      for(int i=2;i<N;++i){
        if(!vis[i])P[++tot]=i,phi[i]=i-1;
        for(int j=1;j<=tot;++j){
          if(i*P[j]>=N)break;
          vis[i*P[j]]=1;
          if(i%P[j])phi[i*P[j]]=phi[i]*phi[P[j]];
          else{phi[i*P[j]]=phi[i]*P[j];break;}
        }
      }
    }
    
    inline int QPow(int d,int z,int Mod)
    {
      int ans=1;
      for(;z;z>>=1,d=1ll*d*d%Mod)if(z&1)ans=1ll*ans*d%Mod;
      return ans;
    }
    
    inline bool check(int x)
    {
      if(x==2 || x==4)return 1;
      if((x&1)^1)x>>=1;
      for(int i=2;P[i]<=x;++i)
        if(x%P[i]==0){
          while(x%P[i]==0)x/=P[i];
          return x==1?P[i]:0;
        }
      return 0;
    }
    
    inline int get_rg(int fx)
    {
      int pt[1010],tt=0,Txd=phi[fx];
      for(int i=1;P[i]*P[i]<=Txd;++i)
        if(Txd%P[i]==0){
          pt[++tt]=P[i];
          while(Txd%P[i]==0)Txd/=P[i];
        }
      if(Txd!=1)pt[++tt]=Txd;
      for(int i=2;i<=fx;++i)
        if(QPow(i,phi[fx],fx)==1){
          int flag=1;
          for(int j=1;j<=tt;++j)
    	if(QPow(i,phi[fx]/pt[j],fx)==1){
    	  flag=0;break;
    	}
          if(flag)return i;
        }
      return 0;
    }
    
    inline void work(int fx)
    {
      int tt=0,pr[N];
      if(fx==2){printf("1
    ");return;}
      if(fx==4){printf("3
    ");return;}
      int T=check(fx);
      if(!T){printf("-1
    ");return;}
      int g=get_rg(fx);
      for(int i=1,k=g;i<phi[fx];++i,k=1ll*k*g%fx)
        if(gcd(i,phi[fx])==1)
          pr[++tt]=k;
      sort(pr+1,pr+tt+1);
      for(int i=1;i<tt;++i)
        printf("%d ",pr[i]);
      printf("%d",pr[tt]);
      printf("
    ");
    }
    
    int main()
    {
      prepare();
      while(scanf("%d",&n)!=EOF)work(n);
      return 0;
    }
    

      

  • 相关阅读:
    Jvascript方法
    Java高效读取大文件(转)
    RandomAccessFile实时读取大文件(转)
    Java中的逆变与协变 专题
    Docker系列之(一):10分钟玩转Docker(转)
    Redis系列之(一):10分钟玩转Redis(转)
    BDB (Berkeley DB)数据库简单介绍(转载)
    JAVA的extends使用方法
    计算机视觉领域的一些牛人博客,超有实力的研究机构等的站点链接
    中国大推力矢量发动机WS15 跨入 世界先进水平!
  • 原文地址:https://www.cnblogs.com/fenghaoran/p/7110296.html
Copyright © 2020-2023  润新知