Нахождение примитивных корней по модулю р трудно, особенно если р очень велико. Я не уверен, есть ли в каждой java-библиотеке встроенная функция GetPrimitive()
, но, следуя нижеприведенному методу, это лучшее, что я встречал (это общий алгоритм, описанный на wikipedia).
Вам необходимо будет создать свою собственную функцию для быстрого экспонирования мод p. Это, как правило, очень легкие задачи рекурсии. Ниже псевдокод, который поможет вам начать:
Function FastExpModP(x as int, n as int, p as int) {
if (n == 0) {
return(1);
} else if (n == 1) {
return(x);
} else if (n mod 2==0) {
return(FastExpModP(x^2 mod p, n/2, p));
} else {
return(x * FastExpModP(x^2 mod p, (n-1)/2, p)) mod p);
}
}
Далее вы должны найти все простые числа, которые делят р - 1 (Не обязательно разложение на простые множители), так как phi(p) = p - 1
. Предположим, что простые множители р - 1 являются следующие: р , р ..., р к (есть несколько опубликованы легко понять алгоритмы для выполнения этой задачи уже, поэтому я оставлю это без запроса).
Теперь все, что требуется, чтобы проверить модульную экспоненциацию Mod р каждого элемента (я обычно начинаю с номером 2) по всем показателям вида
( р - 1)/ р я, для всех 1 < = я < = к
пока не найдете результат, не равный единице для всех показателей. Ниже псевдокод для выполнения этой задачи:
Function GetPrimitive(p as int, pfacs[] as int) {
m = p - 1
for (int i = 2; i <= m; ++i) {
for (int q = 1; q <= pfacs.length; ++q) {
test = FastExpModP(i, m/pfacs[q], p)
if (test==1) {
break;
}
}
if (test > 1) {
return(i);
}
}
}
Например, возьмем простое число P = 28764457.Теперь, м = р - 1 и простые множители м являются:
2, 3, 7, 131, и 1307
и м делится на каждый из приведенных выше простых чисел дает:
14382228, 9588152, 4109208, 219576 и 22008
Теперь мы будем перебирать от 2, проверка модульного возведения в степень Mod р, чтобы увидеть, если результат для каждого показателя равен 1. Мы останавливаемся, когда мы находим такое число, что модульное возведение мод р для каждого показателя не равен 1.
For 2 we have:
2^14382228 = 1 mod p ==>> stop... try 3
For 3 we have:
3^14382228 = 1 mod p ==>> stop... try 4
For 4 we have (same as 2 since 4 = 2^2):
4^14382228 = 1 mod p ==>> stop... try 5
For 5 we have:
5^14382228 = 28764456 mod p, 5^9588152 = 13076987 mod p, 5^4109208 = 1 mod p ==>> stop... try 6
For 6 we have:
6^14382228 = 1 mod p ==>> stop... try 7
For 7 we have:
7^14382228 = 1 mod p ==>> stop... try 8
For 8 we have (same as 2 since 8 = 2^3):
8^14382228 = 1 mod p ==>> stop... try 9
For 9 we have (same as 3 since 9 = 3^2):
9^14382228 = 1 mod p ==>> stop... try 10
For 10 we have:
10^14382228 = 28764456 mod p, 10^9588152 = 15687469 mod p, 10^4109208 = 23392715 mod p
10^219576 = 17852870 mod p, 10^22008 = 5014623 mod p ==>> winner!!!
Таким образом, вызов функции GetPrimitive(28764457, {2, 3, 7, 131, 1307})
вернет 10
как наименьший примитивный корень мод р.
Для получения более математического фона на эту тему, ознакомьтесь с этим mathematics exchange question.
Поскольку ваше простое P имеет особый вид P = 2q + 1, проверка примитивности проста. Так как P-1 = 2q, выберите g! = 1 и если g^2! = 1 и g^q! = 1, то g является примитивным корнем. –
@JamesKPolk, хорошая проницательность. Проведя немного времени, проверяя математику в вашем комментарии, мой ответ ниже, кажется, из темных веков. Почему бы вам не добавить свой комментарий в качестве ответа, поскольку он намного выше? Я бы не хотел, чтобы мой ответ остался основным. Я с радостью выберу его и удалю шахту, чтобы не добавлять шум. –