原根二连 HDU 4992 && poj 1284 Primitive Roots

原根存在的充要条件

n = 1,2,4,p^r (p为奇素数,r为任意正整数)

原根的性质

若n存在原根,则原根个数为φ(φ(n))

若g是n的一个原根,则g^d是n的原根的充要条件为gcd(d,φ(n)) = 1

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

一个数的全体原根和模n余μ(n-1)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
bool isprime[1000001];
LL prime[100001];
LL primesize = 0,n,ans[10001],p;
LL res[1000005];
LL gcd(LL a,LL b){
  if (b == 0) return a;
  return gcd(b,a % b);
}

LL Fast_Mod(LL a,LL b,LL p){
   LL res = 1,base = a;
   while (b){
       if (b&1) res = (res*base) % p;
       base = (base*base) % p;
       b = b >> 1;
   }
   return res;
}

void initPrime(){
  memset(isprime,1,sizeof(isprime));
  isprime[1] = false;
  LL ListSize = 1000000;
  for (LL i=2;i<= ListSize ; i++){
    if (isprime[i]) {
      primesize ++; prime[primesize] = i;
    }
    for (int j=1;j<=primesize && i*prime[j] <= ListSize; j++){
      isprime[i*prime[j]] = false;
      if (i % prime[j] == 0) break;
    }
 }
}

LL phi(LL n){
    LL i,rea=n;
    for(i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            rea=rea-rea/i;
            while(n%i==0)  n/=i;
        }
    }
    if(n>1)
        rea=rea-rea/n;
    return rea;
}

bool exist(LL n){
  if (n % 2 == 0) n /= 2;
  if (isprime[n]) return 1;
  for (int i=3;i*i<=n;i+=2){
    if (n % i == 0){
      while (n % i == 0) n /= i;
      return (n == 1);
    }
  }
  return 0;
}

int main()
{
    // freopen("test.in","r",stdin);
    initPrime();
    while(scanf("%lld",&p)!=-1)
    {
        int cnt=0;
        if (p == 2) {
          cout << 1 << endl; continue;
        }
        if (p == 4){
          cout << 3 << endl; continue;
        }
        if (!exist(p)){
          cout << -1 << endl; continue;
        }
        n = phi(p);
        for(int i=1;i<=primesize&&prime[i]*prime[i]<=n;i++)
        {
            if(n%prime[i]==0)
            {
                n/=prime[i];
                cnt ++;
                ans[cnt]=prime[i];
                while(n%prime[i]==0)
                {
                    n/=prime[i];
                }
            }
        }
        if(n!=1){
          cnt ++;
          ans[cnt]=n;
        }
        n = phi(p);
        LL g;
        for (int i=2;i<p;i++){
          if (gcd(i,p) == 1){
            int ok = 1;
            for (int j=1;j<=cnt;j++){
              if (Fast_Mod(i,n/ans[j],p) == 1){
                ok = 0; break;
              }
            }
            if (ok){
                g = i;
                break;
            }
          }
        }
        LL total = 0;
        for (int i=1;i<=n;i++){
          if (gcd(i,n) == 1){
            total ++;
            res[total] = Fast_Mod(g,i,p);
          }
        }
        sort(res+1,res+total+1);
        for (int i=1;i<=total-1;i++){
          cout << res[i] << " ";
        }
        cout << res[total] << endl;
    }

    return 0;
}

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
bool isprime[1000001];
LL prime[100001];
LL primesize = 0,n,ans[10001],p;

LL gcd(LL a,LL b){
  if (b == 0) return a;
  return gcd(b,a % b);
}

LL Fast_Mod(LL a,LL b,LL p){
   LL res = 1,base = a;
   while (b){
       if (b&1) res = (res*base) % p;
       base = (base*base) % p;
       b = b >> 1;
   }
   return res;
}

void initPrime(){
  memset(isprime,1,sizeof(isprime));
  isprime[1] = false;
  LL ListSize = 1000000;
  for (LL i=2;i<= ListSize ; i++){
    if (isprime[i]) {
      primesize ++; prime[primesize] = i;
    }
    for (int j=1;j<=primesize && i*prime[j] <= ListSize; j++){
      isprime[i*prime[j]] = false;
      if (i % prime[j] == 0) break;
    }
 }
}

LL phi(LL n){
    LL i,rea=n;
    for(i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            rea=rea-rea/i;
            while(n%i==0)  n/=i;
        }
    }
    if(n>1)
        rea=rea-rea/n;
    return rea;
}

int main()
{
    // freopen("test.in","r",stdin);
    initPrime();
    while(scanf("%lld",&p)!=-1)
    {
        int cnt=0;
        n = phi(p);
        for(int i=1;i<=primesize&&prime[i]*prime[i]<=n;i++)
        {
            if(n%prime[i]==0)
            {
                n/=prime[i];
                cnt ++;
                ans[cnt]=prime[i];
                while(n%prime[i]==0)
                {
                    n/=prime[i];
                }
            }
        }
        if(n!=1){
          cnt ++;
          ans[cnt]=n;
        }
        bool find = 0;
        n = phi(p);
        for (int i=2;i<p;i++){
          if (gcd(i,p) == 1){
            int ok = 1;
            for (int j=1;j<=cnt;j++){
              if (Fast_Mod(i,n/ans[j],p) == 1){
                ok = 0; break;
              }
            }
            if (ok){
              find = 1; break;
            }
          }
        }
        if (find){
          cout << phi(phi(p)) << endl;
        }
        else {
          cout << 0 << endl;
        }
    }

    return 0;
}

时间: 2024-10-12 12:55:59

原根二连 HDU 4992 && poj 1284 Primitive Roots的相关文章

POJ 1284 Primitive Roots (求原根个数)

Primitive Roots 题目链接:http://poj.org/problem?id=1284 利用定理:素数 P 的原根的个数为euler(p - 1) typedef long long ll; using namespace std; /* 求原根 g^d ≡ 1(mod p) 其中d最小为p-1,g 便是一个原根 复杂度:O(m)*log(P-1)(m为p-1的质因子个数) */ ll euler(ll x) { ll res = x; for (ll i = 2; i <= x

poj 1284 Primitive Roots 【原根】【数论】

题目链接 :传送门 题目大意: 求一个质数的原根个数. 先普及一下原根的定义: 设m是正整数,a是整数,若a模m的阶等于euler(m),则称a为模m的一个原根. eg: m=7,euler(7) =  6(1,2,3,4,5,6) 则: 1   1^(n)mod7=1! = 6 2   2^(n)mod7={2 4 1}!=6 3   3^(n)mod7={3,2,6,4,5,1}==6   故3是模7的原根 4   4^(n)mod7={4,2,1}!=6 5   5^(n)mod7={5,

POJ 1284 Primitive Roots (原根)

Primitive Roots Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3219   Accepted: 1858 Description We say that integer x, 0 < x < p, is a primitive root modulo odd prime p if and only if the set { (xi mod p) | 1 <= i <= p-1 } is eq

poj 1284 Primitive Roots 求素数元根数

题意: 给奇素数p,求p有多少原根. 分析: phi(p-1),数论有具体证明. 代码: //poj 1284 #include <iostream> using namespace std; int main() { int n; while(scanf("%d",&n)==1){ --n; int ans=n; for(int i=2;i*i<=n;++i) if(n%i==0){ ans-=ans/i; while(n%i==0) n/=i; } if(

POJ 1284 Primitive Roots

Primitive Roots Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5481   Accepted: 3101 Description We say that integer x, 0 < x < p, is a primitive root modulo odd prime p if and only if the set { (xi mod p) | 1 <= i <= p-1 } is eq

poj 1284 Primitive Roots(未完)

Primitive Roots Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3155   Accepted: 1817 Description We say that integer x, 0 < x < p, is a primitive root modulo odd prime p if and only if the set { (xi mod p) | 1 <= i <= p-1 } is eq

poj 1284 Primitive Roots(原根)

定理:假如一个数x有原根,则元根的个数为phi(phi(x)),phi(x)为小于x且与x互质的正整数个数. #include <iostream> #include <cmath> using namespace std; int p; int f(int x){ int ans=x; int m=sqrt(x+0.5); for(int i=2;i<=m;i++)if(x%i==0){ ans=ans/i*(i-1); while(x%i==0)x/=i; } if(x&

POJ 1284 Primitive Roots 欧拉函数模板题

#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <stack> #include <map> #include <ctime> #include <io

【POJ】1284 Primitive Roots

http://poj.org/problem?id=1284 题意:求一个素数p的原根个数.(p<=65535) #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <iostream> using namespace std; const int lim=65535, N=70005; int p[N], pcnt, np[