Последний раз редактировалось wrest 29.06.2025, 03:05, всего редактировалось 2 раз(а).
Тут писать надо. Ну что ж... пришлось написать.
- \\ Написано wrest с помощью DeepSeek
- \\ Фунция sqm(a,m) находит все решения n<m сравнения n^2 = a mod m включая составные модули
- \\ модуль факторизуется, затем отдельно обрабатываются степени двойки и степени нечетных простых.
- \\ Найденные корни для нечетных простых делителей поднимаются до соответстующих степеней
- \\ с использованием леммы Гензеля. Затем корни по простым делителям модуля объединяются с использованием КТО
- \\ китайской теоремы об остатках
- sqm(a, m) = {
- my(factors, solutions_list, mod_list, p, e, sols, solutions, new_solutions, crt_val, i, k, j, x, x0, f, df, inv_df, t, pe, found);
-
- \\ Обработка специальных случаев
- if(m == 1, return([0]));
- if(a == 0, return([0]));
-
- \\ Факторизация модуля
- factors = factor(m);
- if(#factors[,1] == 0, return([]));
-
- solutions_list = [];
- mod_list = [];
-
- \\ Основной цикл по простым делителям
- for(i = 1, #factors[,1],
- p = factors[i,1];
- e = factors[i,2];
- pe = p^e;
- sols = [];
-
- \\ Обработка случая p=2
- if(p == 2,
- \\ Решение для 2^1
- if(e == 1,
- if(a%2 == 0, sols = [0])
- ,
- \\ Решение для 2^2
- if(e == 2,
- if(a%4 == 0, sols = [0, 2]);
- if(a%4 == 1, sols = [1, 3])
- ,
- \\ Решение для 2^k, k>=3
- \\ Рекурсивный поиск решений
- my(x0 = [], x0_temp = []);
- if(a%4 == 0, x0 = [0, 2]);
- if(a%4 == 1, x0 = [1, 3]);
-
- for(k_temp = 3, e,
- x0_temp = [];
- for(idx = 1, #x0,
- x = x0[idx];
- if((x^2 - a) % (2^k_temp) == 0,
- x0_temp = concat(x0_temp, [x]);
- x0_temp = concat(x0_temp, [x + 2^(k_temp-1)]);
- )
- );
- x0 = x0_temp;
- if(#x0 == 0, break);
- );
- sols = x0;
- ))
- ,
- \\ Обработка нечетных простых
- \\ Решение для p^1
- if(e == 1,
- for(x = 0, p-1,
- if(Mod(x, p)^2 == Mod(a, p),
- sols = concat(sols, [x]);
- )
- )
- ,
- \\ Решение для p^k, k>1
- \\ Рекурсивный поиск решений
- my(x0 = [], x0_temp = []);
- for(x = 0, p-1,
- if(Mod(x, p)^2 == Mod(a, p),
- x0 = concat(x0, [x]);
- )
- );
-
- for(k_temp = 2, e,
- x0_temp = [];
- for(idx = 1, #x0,
- x = x0[idx];
- f = x^2 - a;
- df = 2*x;
-
- if(Mod(df, p) != 0,
- inv_df = lift(Mod(df, p^k_temp)^(-1));
- x = (x - f * inv_df) % (p^k_temp);
- x0_temp = concat(x0_temp, [x]);
- ,
- if(Mod(f, p^k_temp) == 0,
- for(t = 0, p-1,
- found = (x + t*p^(k_temp-1)) % (p^k_temp);
- if(Mod(found, p^k_temp)^2 == Mod(a, p^k_temp),
- x0_temp = concat(x0_temp, [found]);
- )
- )
- )
- )
- );
- x0 = x0_temp;
- if(#x0 == 0, break);
- );
- sols = x0;
- )
- );
-
- if(#sols == 0, return([]));
- solutions_list = concat(solutions_list, [sols]);
- mod_list = concat(mod_list, [pe]);
- );
-
- \\ Объединение решений через КТО
- if(#solutions_list == 0, return([]));
- if(#solutions_list == 1, return(solutions_list[1]));
-
- solutions = solutions_list[1];
- for(k = 2, #solutions_list,
- new_solutions = [];
- for(i = 1, #solutions,
- for(j = 1, #solutions_list[k],
- crt_val = chinese(Mod(solutions[i], mod_list[1]), Mod(solutions_list[k][j], mod_list[k]));
- if(crt_val != -1,
- new_solutions = concat(new_solutions, [lift(crt_val)]);
- )
- )
- );
- solutions = new_solutions;
- if(#solutions == 0, return([]));
- );
-
- vecsort(solutions,,8);
- }
Пример (найти такие числа что запись их квадратов оканчивается на 84848484): Код: ? print(sqm(84848484,100^4)) [7292022, 9895478, 15104522, 17707978, 32292022, 34895478, 40104522, 42707978, 57292022, 59895478, 65104522, 67707978, 82292022, 84895478, 90104522, 92707978] ? ## *** last result: cpu time 0 ms, real time 0 ms. ? получить три других: ну вот получилось ещё 15 других 
|