This documentation is automatically generated by online-judge-tools/verification-helper
#include "math/generalized_discrete_logarithm.hpp"template<typename T> generalized_discrete_logarithm(T x, T y, auto f, int n, auto f_m, int m) : $f^n(x) = y$ を満たす $n$ 以下の自然数 $k$ が存在するかどうかを判定し、存在するならその最小値を返す(存在しない場合は $-1$ が返る)。適切な $m$ の設定で$O(\sqrt{N})$
ただし、
[250225離散対数問題](https://acompany-ac.notion.site/250225-1a4269d8558680a8bcbef0b561d04a41)
#pragma once
#include<unordered_set>
template<typename T>
T generalized_discrete_logarithm(T x, T y, auto f, int n, auto f_m, int m){
if(x == y){
return 0;
}
std::unordered_set<T> baby_steps;
T fy = y;
for(int i = 0;i < m;i++){
baby_steps.insert(fy);
fy = f(fy);
}
T fx = x;
bool is_first_loop = true;
for(int i = 0;i <= n;i += m){
T next_val = f_m(fx);
if(baby_steps.contains(next_val)){
for(int j = i+1;j <= i+m;j++){
fx = f(fx);
if(fx == y){
return (j <= n ? j : -1);
}
}
if(is_first_loop){
is_first_loop = false;
}else{
return -1;
}
}
fx = next_val;
}
return -1;
}#line 2 "math/generalized_discrete_logarithm.hpp"
#include<unordered_set>
template<typename T>
T generalized_discrete_logarithm(T x, T y, auto f, int n, auto f_m, int m){
if(x == y){
return 0;
}
std::unordered_set<T> baby_steps;
T fy = y;
for(int i = 0;i < m;i++){
baby_steps.insert(fy);
fy = f(fy);
}
T fx = x;
bool is_first_loop = true;
for(int i = 0;i <= n;i += m){
T next_val = f_m(fx);
if(baby_steps.contains(next_val)){
for(int j = i+1;j <= i+m;j++){
fx = f(fx);
if(fx == y){
return (j <= n ? j : -1);
}
}
if(is_first_loop){
is_first_loop = false;
}else{
return -1;
}
}
fx = next_val;
}
return -1;
}