📜  素数n模n的素数根

📅  最后修改于: 2021-05-04 12:54:41             🧑  作者: Mango

给定质数n,任务是在模n下找到其原始根。质数n的本原根是[1,n-1]之间的整数r,使得x在[0,n-2]范围内的r ^ x(mod n)的值不同。如果n是非质数,则返回-1。

例子:

Input : 7
Output : Smallest primitive root = 3
Explanation: n = 7
3^0(mod 7) = 1
3^1(mod 7) = 3
3^2(mod 7) = 2
3^3(mod 7) = 6
3^4(mod 7) = 4
3^5(mod 7) = 5

Input : 761
Output : Smallest primitive root = 6

一个简单的解决方案是尝试从2到n-1的所有数字。对于每个数字r,计算r ^ x(mod n)的值,其中x在[0,n-2]范围内。如果所有这些值都不相同,则返回r,否则继续下一个r值。如果尝试了r的所有值,则返回-1。

一个有效的解决方案基于以下事实。
如果数字r模n的乘法阶等于Euler Totient函数Φ(n)(请注意素数n的Euler Totient函数为n-1),则它是原始根[来源:Wiki]

1- Euler Totient Function phi = n-1 [Assuming n is prime]
1- Find all prime factors of phi.
2- Calculate all powers to be calculated further 
   using (phi/prime-factors) one by one.
3- Check for all numbered for all powers from i=2 
   to n-1 i.e. (i^ powers) modulo n.
4- If it is 1 then 'i' is not a primitive root of n.
5- If it is never 1 then return i;.

尽管一个质数可以有多个原始根,但我们只关心最小的根,如果要查找所有根,请继续进行直到p-1的过程,而不是分解找到第一个原始根。

C++
// C++ program to find primitive root of a
// given number n
#include
using namespace std;
  
// Returns true if n is prime
bool isPrime(int n)
{
    // Corner cases
    if (n <= 1)  return false;
    if (n <= 3)  return true;
  
    // This is checked so that we can skip
    // middle five numbers in below loop
    if (n%2 == 0 || n%3 == 0) return false;
  
    for (int i=5; i*i<=n; i=i+6)
        if (n%i == 0 || n%(i+2) == 0)
            return false;
  
    return true;
}
  
/* Iterative Function to calculate (x^n)%p in
   O(logy) */
int power(int x, unsigned int y, int p)
{
    int res = 1;     // Initialize result
  
    x = x % p; // Update x if it is more than or
    // equal to p
  
    while (y > 0)
    {
        // If y is odd, multiply x with result
        if (y & 1)
            res = (res*x) % p;
  
        // y must be even now
        y = y >> 1; // y = y/2
        x = (x*x) % p;
    }
    return res;
}
  
// Utility function to store prime factors of a number
void findPrimefactors(unordered_set &s, int n)
{
    // Print the number of 2s that divide n
    while (n%2 == 0)
    {
        s.insert(2);
        n = n/2;
    }
  
    // n must be odd at this point. So we can skip
    // one element (Note i = i +2)
    for (int i = 3; i <= sqrt(n); i = i+2)
    {
        // While i divides n, print i and divide n
        while (n%i == 0)
        {
            s.insert(i);
            n = n/i;
        }
    }
  
    // This condition is to handle the case when
    // n is a prime number greater than 2
    if (n > 2)
        s.insert(n);
}
  
// Function to find smallest primitive root of n
int findPrimitive(int n)
{
    unordered_set s;
  
    // Check if n is prime or not
    if (isPrime(n)==false)
        return -1;
  
    // Find value of Euler Totient function of n
    // Since n is a prime number, the value of Euler
    // Totient function is n-1 as there are n-1
    // relatively prime numbers.
    int phi = n-1;
  
    // Find prime factors of phi and store in a set
    findPrimefactors(s, phi);
  
    // Check for every number from 2 to phi
    for (int r=2; r<=phi; r++)
    {
        // Iterate through all prime factors of phi.
        // and check if we found a power with value 1
        bool flag = false;
        for (auto it = s.begin(); it != s.end(); it++)
        {
  
            // Check if r^((phi)/primefactors) mod n
            // is 1 or not
            if (power(r, phi/(*it), n) == 1)
            {
                flag = true;
                break;
            }
         }
  
         // If there was no power with value 1.
         if (flag == false)
           return r;
    }
  
    // If no primitive root found
    return -1;
}
  
// Driver code
int main()
{
    int n = 761;
    cout << " Smallest primitive root of " << n
         << " is " << findPrimitive(n);
    return 0;
}


Java
// Java program to find primitive root of a
// given number n
import java.util.*;
  
class GFG
{
  
    // Returns true if n is prime
    static boolean isPrime(int n) 
    {
        // Corner cases
        if (n <= 1)
        {
            return false;
        }
        if (n <= 3) 
        {
            return true;
        }
  
        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0) 
        {
            return false;
        }
  
        for (int i = 5; i * i <= n; i = i + 6) 
        {
            if (n % i == 0 || n % (i + 2) == 0) 
            {
                return false;
            }
        }
  
        return true;
    }
  
    /* Iterative Function to calculate (x^n)%p in
    O(logy) */
    static int power(int x, int y, int p)
    {
        int res = 1;     // Initialize result
  
        x = x % p; // Update x if it is more than or
        // equal to p
  
        while (y > 0) 
        {
            // If y is odd, multiply x with result
            if (y % 2 == 1) 
            {
                res = (res * x) % p;
            }
  
            // y must be even now
            y = y >> 1; // y = y/2
            x = (x * x) % p;
        }
        return res;
    }
  
    // Utility function to store prime factors of a number
    static void findPrimefactors(HashSet s, int n) 
    {
        // Print the number of 2s that divide n
        while (n % 2 == 0) 
        {
            s.add(2);
            n = n / 2;
        }
  
        // n must be odd at this point. So we can skip
        // one element (Note i = i +2)
        for (int i = 3; i <= Math.sqrt(n); i = i + 2) 
        {
            // While i divides n, print i and divide n
            while (n % i == 0) 
            {
                s.add(i);
                n = n / i;
            }
        }
  
        // This condition is to handle the case when
        // n is a prime number greater than 2
        if (n > 2) 
        {
            s.add(n);
        }
    }
  
    // Function to find smallest primitive root of n
    static int findPrimitive(int n) 
    {
        HashSet s = new HashSet();
  
        // Check if n is prime or not
        if (isPrime(n) == false) 
        {
            return -1;
        }
  
        // Find value of Euler Totient function of n
        // Since n is a prime number, the value of Euler
        // Totient function is n-1 as there are n-1
        // relatively prime numbers.
        int phi = n - 1;
  
        // Find prime factors of phi and store in a set
        findPrimefactors(s, phi);
  
        // Check for every number from 2 to phi
        for (int r = 2; r <= phi; r++) 
        {
            // Iterate through all prime factors of phi.
            // and check if we found a power with value 1
            boolean flag = false;
            for (Integer a : s) 
            {
  
                // Check if r^((phi)/primefactors) mod n
                // is 1 or not
                if (power(r, phi / (a), n) == 1) 
                {
                    flag = true;
                    break;
                }
            }
  
            // If there was no power with value 1.
            if (flag == false)
            {
                return r;
            }
        }
  
        // If no primitive root found
        return -1;
    }
  
    // Driver code
    public static void main(String[] args) 
    {
        int n = 761;
        System.out.println(" Smallest primitive root of " + n
                + " is " + findPrimitive(n));
    }
}
  
/* This code contributed by PrinciRaj1992 */


Python3
# Python3 program to find primitive root 
# of a given number n 
from math import sqrt
  
# Returns True if n is prime 
def isPrime( n): 
  
    # Corner cases 
    if (n <= 1):
        return False
    if (n <= 3):
        return True
  
    # This is checked so that we can skip 
    # middle five numbers in below loop 
    if (n % 2 == 0 or n % 3 == 0):
        return False
    i = 5
    while(i * i <= n):
        if (n % i == 0 or n % (i + 2) == 0) :
            return False
        i = i + 6
  
    return True
  
""" Iterative Function to calculate (x^n)%p
    in O(logy) */"""
def power( x, y, p): 
  
    res = 1 # Initialize result 
  
    x = x % p # Update x if it is more 
              # than or equal to p 
  
    while (y > 0): 
  
        # If y is odd, multiply x with result 
        if (y & 1):
            res = (res * x) % p 
  
        # y must be even now 
        y = y >> 1 # y = y/2 
        x = (x * x) % p 
  
    return res 
  
# Utility function to store prime
# factors of a number 
def findPrimefactors(s, n) :
  
    # Print the number of 2s that divide n 
    while (n % 2 == 0) :
        s.add(2) 
        n = n // 2
  
    # n must be odd at this po. So we can  
    # skip one element (Note i = i +2) 
    for i in range(3, int(sqrt(n)), 2):
          
        # While i divides n, print i and divide n 
        while (n % i == 0) :
  
            s.add(i) 
            n = n // i 
          
    # This condition is to handle the case 
    # when n is a prime number greater than 2 
    if (n > 2) :
        s.add(n) 
  
# Function to find smallest primitive 
# root of n 
def findPrimitive( n) :
    s = set() 
  
    # Check if n is prime or not 
    if (isPrime(n) == False): 
        return -1
  
    # Find value of Euler Totient function 
    # of n. Since n is a prime number, the 
    # value of Euler Totient function is n-1 
    # as there are n-1 relatively prime numbers.
    phi = n - 1
  
    # Find prime factors of phi and store in a set 
    findPrimefactors(s, phi) 
  
    # Check for every number from 2 to phi 
    for r in range(2, phi + 1): 
  
        # Iterate through all prime factors of phi. 
        # and check if we found a power with value 1 
        flag = False
        for it in s: 
  
            # Check if r^((phi)/primefactors)
            # mod n is 1 or not 
            if (power(r, phi // it, n) == 1): 
  
                flag = True
                break
              
        # If there was no power with value 1. 
        if (flag == False):
            return r 
  
    # If no primitive root found 
    return -1
  
# Driver Code 
n = 761
print("Smallest primitive root of", 
         n, "is", findPrimitive(n))
  
# This code is contributed by
# Shubham Singh(SHUBHAMSINGH10)


C#
// C# program to find primitive root of a
// given number n 
using System;
using System.Collections.Generic;
  
class GFG
{
  
    // Returns true if n is prime
    static bool isPrime(int n) 
    {
        // Corner cases
        if (n <= 1)
        {
            return false;
        }
        if (n <= 3) 
        {
            return true;
        }
  
        // This is checked so that we can skip
        // middle five numbers in below loop
        if (n % 2 == 0 || n % 3 == 0) 
        {
            return false;
        }
  
        for (int i = 5; i * i <= n; i = i + 6) 
        {
            if (n % i == 0 || n % (i + 2) == 0) 
            {
                return false;
            }
        }
  
        return true;
    }
  
    /* Iterative Function to calculate (x^n)%p in
    O(logy) */
    static int power(int x, int y, int p)
    {
        int res = 1;     // Initialize result
  
        x = x % p; // Update x if it is more than or
        // equal to p
  
        while (y > 0) 
        {
            // If y is odd, multiply x with result
            if (y % 2 == 1) 
            {
                res = (res * x) % p;
            }
  
            // y must be even now
            y = y >> 1; // y = y/2
            x = (x * x) % p;
        }
        return res;
    }
  
    // Utility function to store prime factors of a number
    static void findPrimefactors(HashSet s, int n) 
    {
        // Print the number of 2s that divide n
        while (n % 2 == 0) 
        {
            s.Add(2);
            n = n / 2;
        }
  
        // n must be odd at this point. So we can skip
        // one element (Note i = i +2)
        for (int i = 3; i <= Math.Sqrt(n); i = i + 2) 
        {
            // While i divides n, print i and divide n
            while (n % i == 0) 
            {
                s.Add(i);
                n = n / i;
            }
        }
  
        // This condition is to handle the case when
        // n is a prime number greater than 2
        if (n > 2) 
        {
            s.Add(n);
        }
    }
  
    // Function to find smallest primitive root of n
    static int findPrimitive(int n) 
    {
        HashSet s = new HashSet();
  
        // Check if n is prime or not
        if (isPrime(n) == false) 
        {
            return -1;
        }
  
        // Find value of Euler Totient function of n
        // Since n is a prime number, the value of Euler
        // Totient function is n-1 as there are n-1
        // relatively prime numbers.
        int phi = n - 1;
  
        // Find prime factors of phi and store in a set
        findPrimefactors(s, phi);
  
        // Check for every number from 2 to phi
        for (int r = 2; r <= phi; r++) 
        {
            // Iterate through all prime factors of phi.
            // and check if we found a power with value 1
            bool flag = false;
            foreach (int a in s) 
            {
  
                // Check if r^((phi)/primefactors) mod n
                // is 1 or not
                if (power(r, phi / (a), n) == 1) 
                {
                    flag = true;
                    break;
                }
            }
  
            // If there was no power with value 1.
            if (flag == false)
            {
                return r;
            }
        }
  
        // If no primitive root found
        return -1;
    }
  
    // Driver code
    public static void Main(String[] args) 
    {
        int n = 761;
        Console.WriteLine(" Smallest primitive root of " + n
                + " is " + findPrimitive(n));
    }
}
  
// This code is contributed by Rajput-Ji


输出:

Smallest primitive root of 761 is 6

参考:
https://zh.wikipedia.org/wiki/Primitive_root_modulo_n#Finding_primitive_roots
http://math.stackexchange.com/questions/124408/finding-a-primitive-root-of-a-prime-number