Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

ค้นหาจำนวนโมดูโลไพรม์รูตดั้งเดิมใน C++


ในปัญหานี้ เราได้รับจำนวนเฉพาะ N หน้าที่ของเราคือ หาจำนวนโมดูโลไพรม์ของรากดั้งเดิม .

รากดั้งเดิมของตัวเลข − เป็นตัวเลข (r) ที่น้อยกว่า N ซึ่งมีค่าทั้งหมดของ r^x(mod N) ที่แตกต่างกันสำหรับ X ทั้งหมดในช่วง [0, n-2]

มาดูตัวอย่างเพื่อทำความเข้าใจปัญหากัน

Input : N = 5
Output : 2

แนวทางการแก้ปัญหา

วิธีแก้ปัญหาอย่างง่ายขึ้นอยู่กับวิธีการทดลองใช้ เราจะตรวจสอบตัวเลขทั้งหมดตั้งแต่ 2 ถึง (N-1) สำหรับเงื่อนไขที่มี x ตั้งแต่ [0, n-2] และแตกหากพบค่าที่ตรงตามเงื่อนไข

โซลูชันนี้ไร้เดียงสาและใช้งานง่าย แต่ความซับซ้อนของเวลาของโซลูชันอยู่ในลำดับของ N 2 . ซึ่งอาจนำไปสู่การดำเนินการระยะยาวในกรณีที่มีค่า N.

. มาก

ดังนั้น วิธีแก้ปัญหาที่มีประสิทธิภาพมากขึ้นคือการใช้ฟังก์ชันออยเลอร์ โทเทียน φ(N)

ดังนั้น สำหรับจำนวน r จะเป็นรากดั้งเดิมของ N ลำดับการคูณด้วยโมดูโล N เท่ากับ φ(N) ต่อไปนี้เป็นขั้นตอนที่ต้องปฏิบัติตาม -

เราต้องหาตัวประกอบเฉพาะของ (N-1) สำหรับจำนวนเฉพาะ N แล้วคำนวณกำลังทั้งหมดโดยใช้ (N-1) / ตัวประกอบเฉพาะ จากนั้นตรวจสอบค่าของจำนวนเฉพาะกำลัง โมดูโล n ถ้ามันไม่ใช่ 1 แสดงว่าฉันเป็นรากดั้งเดิม ค่าแรกที่เราเห็นจะเป็นค่าที่ส่งคืน เนื่องจากมีรากดั้งเดิมมากกว่าหนึ่งค่าสำหรับตัวเลข แต่เราต้องการเพียงค่าที่น้อยที่สุดเท่านั้น

ตัวอย่าง

มาดูตัวอย่างทำความเข้าใจปัญหากัน

#include<bits/stdc++.h>
using namespace std;
int calcPowerMod(int x, unsigned int y, int p){
   int modVal = 1;
   x = x % p;
   while (y > 0){
      if (y & 1)
         modVal = (modVal*x) % p;
      y = y >> 1;
      x = (x*x) % p;
   }
   return modVal;
}
void findAllPrimeFactors(unordered_set<int> &s, int n){
   while (n%2 == 0){
      s.insert(2);
      n = n/2;
   }
   for (int i = 3; i*i <= n; i = i+2){
      while (n%i == 0){
         s.insert(i);
         n = n/i;
      }
   }
   if (n > 2)
      s.insert(n);
}
int findSmallestPrimitiveRoot(int n){
   unordered_set<int> primes;
   int phi = n-1;
   findAllPrimeFactors(primes, phi);
   for (int r=2; r<=phi; r++){
      bool flag = false;
      for (auto it = primes.begin(); it != primes.end(); it++){
         if (calcPowerMod(r, phi/(*it), n) == 1){
            flag = true;
            break;
         }
      }
      if (flag == false)
         return r;
   }
   return -1;
}
int main(){
   int n = 809;
   cout<<"The smallest primitive root is "<<findSmallestPrimitiveRoot(n);
   return 0;
}

ผลลัพธ์

The smallest primitive root is 3