HDU

来源:互联网 发布:java 同步互斥 编辑:程序博客网 时间:2024/06/05 12:43



题意: 

     

          让你求出一个数的全部原根,如果没有,输出-1;


题解“:


          首先先判断该数有无原根,

          一个数x若有原根 则必然满足 n=1,2,4,2p,p^r

          若有原根,再暴力枚举找到最小的原根,分解质因数phi(n);

          则从2~n-1 中有a 满足 a^phi(n)mod n=1  则a 不是n的原根。

  找到最小原根后

  如果g为n的原根,则gd为m的原根的充要条件是gcd(d,φ(n))=1;

       然后递推出所有结果。

1.有原根的数只有2,4,p^n,2p^n(p为质数,n为正整数)。

2.一个数的最小原根的大小是O(n0.25)的。

3.如果g为n的原根,则gd为m的原根的充要条件是(d,φ(n))=1;

4.如果n有原根,它的原根个数为φ(φ(n))。

5.一个数n的全体原根乘积模n余1

6.一个数n的全体原根总和模n余μ(n-1)(莫比乌斯函数)

#include<iostream>#include<cstdio>#include<vector>#include<cmath>#include<cstring>#include<algorithm>using namespace std;#define ll long longconst int maxn=1e6+5;int a[10000];bool p[maxn];int ans[maxn];int cnt;ll gcd(ll a,ll b){    ll t;    while(b){        t=a;a=b;b=t%b;    }    if(a>=0) return a;    else return -a;}int phi(int x){    if(p[x]) return x-1;    int ret=x;    for(int i=2;i<=x;++i){        if(x%i==0){            while(x%i==0) x/=i;            ret=ret-ret/i;        }    }    if(x>1)        ret=ret-ret/x;    return ret;}bool check(int x){    if(x%2==0) x/=2;    if(p[x]) return true;    for(int i=3;i*i<=x;i+=2){        if(x%i==0){            while(x%i==0) x/=i;            return x==1;        }    }    return 0;}void get_x(int x){    cnt=0;    if(p[x]) return ;    for(int i=2;i*i<=x;++i){        if(x%i==0)            a[++cnt]=i;        if(i*i!=x) a[++cnt]=x/i;        //while(x%i==0) x/=i;    }}int kru(int a,int b,int mod){    ll ret=1;    ll t=a;    while(b){        if(b&1)            ret=(ret*t)%mod;        t=t*t%mod;        b>>=1;    }    return (int)ret;}void init(){    memset(p,1,sizeof(p));    p[0]=p[1]=false;    for(int i=2;i<maxn;++i)        if(p[i]){            for(int j=i+i;j<maxn;j+=i)                p[j]=false;        }}int main(){    init();    int n;    while(~scanf("%d",&n)){        if(n==2){            puts("1");continue;        }        if(n==4){            puts("3");continue;        }        if(check(n)==0) {            puts("-1");continue;        }        int t=phi(n);        //printf("phi(%d)=%d\n",n,t);        get_x(t);        int x=-1;        for(int i=2;i<n;++i){            int f=1;            if(kru(i,t,n)!=1) continue;            for(int j=1;j<=cnt;++j){                if(kru(i,a[j],n)==1){                    f=0;break;                }            }            if(f){                x=i;                ans[0]=i;                break;            }        }        if(x==-1){            puts("-1");continue;        }        cnt=0;        for(int i=2;i<t;++i){            if(gcd(i,t)==1)                ans[++cnt]=kru(x,i,n);        }        sort(ans,ans+cnt+1);        printf("%d",ans[0]);        for(int i=1;i<=cnt;++i)            printf(" %d",ans[i]);        puts("");    }    return 0;}


原创粉丝点击