ในปัญหานี้ เราได้รับค่าสี่ค่า A, B, C, M (จำนวนเฉพาะ) งานของเราคือ หาค่ายกกำลังซ้อนภายใต้ modulo ของจำนวนเฉพาะ
เราต้องการหาค่าของ (A ^ (B ^ C)) (mod M)
มาดูตัวอย่างเพื่อเข้าใจปัญหา
Input
A = 3, B = 6, C = 2, M = 11
Output
3
อธิบาย
(A ^ (B ^ C)) = (3 ^ (6 ^ 2)) = (3 ^ (36)) (mod 11) = 3
วิธีแก้ปัญหา
วิธีแก้ที่ง่ายคือคำนวณค่า (A ^ (B ^ C)) โดยตรง ซึ่งทำโดยคำนวณค่า (B^C) ก่อน แล้วค่อย (A ^ (B ^ C)) แล้วหา modulo แต่ (B^C) จะให้ค่ามากมาย การเก็บอาจเป็นปัญหา และการคำนวณอาจเกิด overflow
ดังนั้น วิธีที่มีประสิทธิภาพมากกว่าคือใช้ทฤษฎีบทเล็กของ Fermat (Fermat's Little Theorem) เพื่อหาค่า
ทฤษฎย์บทคือ
a^(m-1) = 1 (mod M) โดยที่ m เป็นจำนวนเฉพาะ
ใช้ทฤษฎีนี้ เราจะแปลง bc ของปัญหาเราให้อยู่ในรูป
x*(M-1) + y สำหรับค่า M ที่กำหนด
โดยใช้ทฤษฎีของ Fermat ส่วน A^(x*(M-1)) จะกลายเป็น 1
สิ่งนี้ลดการคำนวณเหลือ การหาค่า A^y
ค่าของ y สามารถคำนวณได้จาก
B^c = x*(M-1) + y
ทำให้ y เป็นเศษที่เหลือเมื่อเราหาร B^c ด้วย (M-1)
ดังนั้น y = B^c % (M-1)
นี่ทำให้ผลลัพธ์ง่ายขึ้นมาก เราต้องหาแค่
(A ^ ((B^C) % (M-1)) % M
โปรแกรมแสดงการทำงานของวิธีแก้
ตัวอย่าง
#include<iostream>
using namespace std;
int calcPowerMod(int x, int y, int p) {
int powMod = 1;
x = x % p;
while (y > 0) {
if (y & 1)
powMod = (powMod*x) % p;
y /= 2;
x = (x*x) % p;
}
return powMod;
}
int findPowerOfPowerMod(int A, int B, int C, int M) {
return calcPowerMod(A, calcPowerMod(B, C, M-1), M);
}
int main() {
int A = 3, B = 6, C = 2, M = 11;
cout<<"The power of power under modulo is "<<findPowerOfPowerMod(A, B, C, M);
return 0;
}
ผลลัพธ์
The power of power under modulo is 3