HDU - 4992 Primitive Roots 【原根】



题意: 

     

          让你求出一个数的全部原根,如果没有,输出-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
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
const 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


你可能感兴趣的:(数学)