给定三个整数a,b和m。找出一个整数k使得其中a和m是相对质数。如果任何k都不可能满足此关系,则打印-1。
例子:
Input: 2 3 5
Output: 3
Explanation:
a = 2, b = 3, m = 5
The value which satisfies the above equation
is 3, because
=> 23 = 2 * 2 * 2 = 8
=> 23 (mod 5) = 8 (mod 5)
=> 3
which is equal to b i.e., 3.
Input: 3 7 11
Output: -1
幼稚的方法是运行一个从0到m的循环以覆盖k的所有可能值,并检查上述关系是否满足k的值。如果k的所有值均用尽,则打印-1。 Thuis方法的时间复杂度为O(m)
一种有效的方法是通过在中间的技巧中使用Meet来使用婴儿步,巨型步算法。
婴儿步巨步算法
给定一个阶次为’m’的循环群G,该群的生成器’a’和一个群元素’b’,问题是要找到一个整数’k’,使得
因此,我们要做的(根据中间技巧中的Meet)是将问题分为以下两个部分: 分别解决它们,然后找到碰撞。
现在根据婴儿步长巨步算法,我们可以将“ k”写为和和和 。因此,我们有: 因此为了解决,我们预先计算对于不同的“ i”值。然后修复’b’并尝试上述同余关系的RHS中的’j’值。它使用LHS的预先计算的值进行测试,以查看是否满足任何’j’值。
让我们看看如何使用上述算法解决我们的问题:
首先我们要写 , 在哪里显然,间隔[0,m)中k的任何值都可以用这种形式表示,其中和
替换上面的等式中的“ k”,我们得到:
- 左右项只能取n个不同的值,例如 。因此,我们需要为相等的左或右部分生成所有这些术语,并将它们存储在数组或数据结构中,例如C / C++中的map / unordered_map或Java的Hashmap。
- 假设我们已经存储了所有LHS值。现在,遍历RHS上所有可能的条件以获取j的不同值,并检查哪个值满足LHS相等性。
- 如果上述步骤中j的任何候选值都不满足,则打印-1。
C++
// C++ program to calculate discrete logarithm
#include
using namespace std;
/* Iterative Function to calculate (x ^ y)%p in
O(log y) */
int powmod(int x, int y, int p)
{
int res = 1; // Initialize result
x = x % p; // Update x if it is more than or
// equal to p
while (y > 0)
{
// If y is odd, multiply x with result
if (y & 1)
res = (res*x) % p;
// y must be even now
y = y>>1; // y = y/2
x = (x*x) % p;
}
return res;
}
// Function to calculate k for given a, b, m
int discreteLogarithm(int a, int b, int m) {
int n = (int) sqrt (m) + 1;
unordered_map value;
// Store all values of a^(n*i) of LHS
for (int i = n; i >= 1; --i)
value[ powmod (a, i * n, m) ] = i;
for (int j = 0; j < n; ++j)
{
// Calculate (a ^ j) * b and check
// for collision
int cur = (powmod (a, j, m) * b) % m;
// If collision occurs i.e., LHS = RHS
if (value[cur])
{
int ans = value[cur] * n - j;
// Check whether ans lies below m or not
if (ans < m)
return ans;
}
}
return -1;
}
// Driver code
int main()
{
int a = 2, b = 3, m = 5;
cout << discreteLogarithm(a, b, m) << endl;
a = 3, b = 7, m = 11;
cout << discreteLogarithm(a, b, m);
}
Java
// Java program to calculate discrete logarithm
class GFG{
/* Iterative Function to calculate (x ^ y)%p in
O(log y) */
static int powmod(int x, int y, int p)
{
int res = 1; // Initialize result
x = x % p; // Update x if it is more than or
// equal to p
while (y > 0)
{
// If y is odd, multiply x with result
if ((y & 1)>0)
res = (res*x) % p;
// y must be even now
y = y>>1; // y = y/2
x = (x*x) % p;
}
return res;
}
// Function to calculate k for given a, b, m
static int discreteLogarithm(int a, int b, int m) {
int n = (int) (Math.sqrt (m) + 1);
int[] value=new int[m];
// Store all values of a^(n*i) of LHS
for (int i = n; i >= 1; --i)
value[ powmod (a, i * n, m) ] = i;
for (int j = 0; j < n; ++j)
{
// Calculate (a ^ j) * b and check
// for collision
int cur = (powmod (a, j, m) * b) % m;
// If collision occurs i.e., LHS = RHS
if (value[cur]>0)
{
int ans = value[cur] * n - j;
// Check whether ans lies below m or not
if (ans < m)
return ans;
}
}
return -1;
}
// Driver code
public static void main(String[] args)
{
int a = 2, b = 3, m = 5;
System.out.println(discreteLogarithm(a, b, m));
a = 3;
b = 7;
m = 11;
System.out.println(discreteLogarithm(a, b, m));
}
}
// This code is contributed by mits
Python3
# Python3 program to calculate
# discrete logarithm
import math;
# Iterative Function to calculate
# (x ^ y)%p in O(log y)
def powmod(x, y, p):
res = 1; # Initialize result
x = x % p; # Update x if it is more
# than or equal to p
while (y > 0):
# If y is odd, multiply x with result
if (y & 1):
res = (res * x) % p;
# y must be even now
y = y >> 1; # y = y/2
x = (x * x) % p;
return res;
# Function to calculate k for given a, b, m
def discreteLogarithm(a, b, m):
n = int(math.sqrt(m) + 1);
value = [0] * m;
# Store all values of a^(n*i) of LHS
for i in range(n, 0, -1):
value[ powmod (a, i * n, m) ] = i;
for j in range(n):
# Calculate (a ^ j) * b and check
# for collision
cur = (powmod (a, j, m) * b) % m;
# If collision occurs i.e., LHS = RHS
if (value[cur]):
ans = value[cur] * n - j;
# Check whether ans lies below m or not
if (ans < m):
return ans;
return -1;
# Driver code
a = 2;
b = 3;
m = 5;
print(discreteLogarithm(a, b, m));
a = 3;
b = 7;
m = 11;
print(discreteLogarithm(a, b, m));
# This code is contributed by mits
C#
// C# program to calculate discrete logarithm
using System;
class GFG{
/* Iterative Function to calculate (x ^ y)%p in
O(log y) */
static int powmod(int x, int y, int p)
{
int res = 1; // Initialize result
x = x % p; // Update x if it is more than or
// equal to p
while (y > 0)
{
// If y is odd, multiply x with result
if ((y & 1)>0)
res = (res*x) % p;
// y must be even now
y = y>>1; // y = y/2
x = (x*x) % p;
}
return res;
}
// Function to calculate k for given a, b, m
static int discreteLogarithm(int a, int b, int m) {
int n = (int) (Math.Sqrt (m) + 1);
int[] value=new int[m];
// Store all values of a^(n*i) of LHS
for (int i = n; i >= 1; --i)
value[ powmod (a, i * n, m) ] = i;
for (int j = 0; j < n; ++j)
{
// Calculate (a ^ j) * b and check
// for collision
int cur = (powmod (a, j, m) * b) % m;
// If collision occurs i.e., LHS = RHS
if (value[cur]>0)
{
int ans = value[cur] * n - j;
// Check whether ans lies below m or not
if (ans < m)
return ans;
}
}
return -1;
}
// Driver code
static void Main()
{
int a = 2, b = 3, m = 5;
Console.WriteLine(discreteLogarithm(a, b, m));
a = 3;
b = 7;
m = 11;
Console.WriteLine(discreteLogarithm(a, b, m));
}
}
// This code is contributed by mits
PHP
0)
{
// If y is odd, multiply x with result
if ($y & 1)
$res = ($res * $x) % $p;
// y must be even now
$y = $y >> 1; // y = y/2
$x = ($x * $x) % $p;
}
return $res;
}
// Function to calculate k for given a, b, m
function discreteLogarithm($a, $b, $m)
{
$n = (int)sqrt($m) + 1;
$value = array_fill(0, $m, NULL);
// Store all values of a^(n*i) of LHS
for ($i = $n; $i >= 1; --$i)
$value[ powmod ($a, $i * $n, $m) ] = $i;
for ($j = 0; $j < $n; ++$j)
{
// Calculate (a ^ j) * b and check
// for collision
$cur = (powmod ($a, $j, $m) * $b) % $m;
// If collision occurs i.e., LHS = RHS
if ($value[$cur])
{
$ans = $value[$cur] * $n - $j;
// Check whether ans lies below m or not
if ($ans < $m)
return $ans;
}
}
return -1;
}
// Driver code
$a = 2;
$b = 3;
$m = 5;
echo discreteLogarithm($a, $b, $m), "\n";
$a = 3;
$b = 7;
$m = 11;
echo discreteLogarithm($a, $b, $m), "\n";
// This code is contributed by ajit.
?>
C++
// C++ program to calculate discrete logarithm
#include
using namespace std;
int discreteLogarithm(int a, int b, int m)
{
int n = (int) sqrt (m) + 1;
// Calculate a ^ n
int an = 1;
for (int i = 0; i value;
// Store all values of a^(n*i) of LHS
for (int i = 1, cur = an; i<= n; ++i)
{
if (! value[ cur ])
value[ cur ] = i;
cur = (cur * an) % m;
}
for (int i = 0, cur = b; i<= n; ++i)
{
// Calculate (a ^ j) * b and check
// for collision
if (value[cur])
{
int ans = value[cur] * n - i;
if (ans < m)
return ans;
}
cur = (cur * a) % m;
}
return -1;
}
// Driver code
int main()
{
int a = 2, b = 3, m = 5;
cout << discreteLogarithm(a, b, m) << endl;
a = 3, b = 7, m = 11;
cout << discreteLogarithm(a, b, m);
}
Java
// Java program to calculate discrete logarithm
class GFG
{
static int discreteLogarithm(int a, int b, int m)
{
int n = (int) (Math.sqrt (m) + 1);
// Calculate a ^ n
int an = 1;
for (int i = 0; i < n; ++i)
an = (an * a) % m;
int[] value=new int[m];
// Store all values of a^(n*i) of LHS
for (int i = 1, cur = an; i <= n; ++i)
{
if (value[ cur ] == 0)
value[ cur ] = i;
cur = (cur * an) % m;
}
for (int i = 0, cur = b; i <= n; ++i)
{
// Calculate (a ^ j) * b and check
// for collision
if (value[cur] > 0)
{
int ans = value[cur] * n - i;
if (ans < m)
return ans;
}
cur = (cur * a) % m;
}
return -1;
}
// Driver code
public static void main(String[] args)
{
int a = 2, b = 3, m = 5;
System.out.println(discreteLogarithm(a, b, m));
a = 3;
b = 7;
m = 11;
System.out.println(discreteLogarithm(a, b, m));
}
}
// This code is contributed by mits
Python3
# Python3 program to calculate
# discrete logarithm
import math;
def discreteLogarithm(a, b, m):
n = int(math.sqrt (m) + 1);
# Calculate a ^ n
an = 1;
for i in range(n):
an = (an * a) % m;
value = [0] * m;
# Store all values of a^(n*i) of LHS
cur = an;
for i in range(1, n + 1):
if (value[ cur ] == 0):
value[ cur ] = i;
cur = (cur * an) % m;
cur = b;
for i in range(n + 1):
# Calculate (a ^ j) * b and check
# for collision
if (value[cur] > 0):
ans = value[cur] * n - i;
if (ans < m):
return ans;
cur = (cur * a) % m;
return -1;
# Driver code
a = 2;
b = 3;
m = 5;
print(discreteLogarithm(a, b, m));
a = 3;
b = 7;
m = 11;
print(discreteLogarithm(a, b, m));
# This code is contributed by mits
C#
// C# program to calculate discrete logarithm
using System;
class GFG
{
static int discreteLogarithm(int a, int b, int m)
{
int n = (int) (Math.Sqrt (m) + 1);
// Calculate a ^ n
int an = 1;
for (int i = 0; i < n; ++i)
an = (an * a) % m;
int[] value = new int[m];
// Store all values of a^(n*i) of LHS
for (int i = 1, cur = an; i<= n; ++i)
{
if (value[ cur ] == 0)
value[ cur ] = i;
cur = (cur * an) % m;
}
for (int i = 0, cur = b; i<= n; ++i)
{
// Calculate (a ^ j) * b and check
// for collision
if (value[cur] > 0)
{
int ans = value[cur] * n - i;
if (ans < m)
return ans;
}
cur = (cur * a) % m;
}
return -1;
}
// Driver code
static void Main()
{
int a = 2, b = 3, m = 5;
Console.WriteLine(discreteLogarithm(a, b, m));
a = 3;
b = 7;
m = 11;
Console.WriteLine(discreteLogarithm(a, b, m));
}
}
// This code is contributed by mits
PHP
输出:
3
-1
时间复杂度: O(sqrt(m)* log(b))
辅助空间: O(sqrt(m))
一种可能的改进是在算法的第二阶段中消除二进制乘幂或log(b)因子。这可以通过保持每次乘以“ a”的变量作为“ an”来完成。让我们看一下该程序以了解更多信息。
C++
// C++ program to calculate discrete logarithm
#include
using namespace std;
int discreteLogarithm(int a, int b, int m)
{
int n = (int) sqrt (m) + 1;
// Calculate a ^ n
int an = 1;
for (int i = 0; i value;
// Store all values of a^(n*i) of LHS
for (int i = 1, cur = an; i<= n; ++i)
{
if (! value[ cur ])
value[ cur ] = i;
cur = (cur * an) % m;
}
for (int i = 0, cur = b; i<= n; ++i)
{
// Calculate (a ^ j) * b and check
// for collision
if (value[cur])
{
int ans = value[cur] * n - i;
if (ans < m)
return ans;
}
cur = (cur * a) % m;
}
return -1;
}
// Driver code
int main()
{
int a = 2, b = 3, m = 5;
cout << discreteLogarithm(a, b, m) << endl;
a = 3, b = 7, m = 11;
cout << discreteLogarithm(a, b, m);
}
Java
// Java program to calculate discrete logarithm
class GFG
{
static int discreteLogarithm(int a, int b, int m)
{
int n = (int) (Math.sqrt (m) + 1);
// Calculate a ^ n
int an = 1;
for (int i = 0; i < n; ++i)
an = (an * a) % m;
int[] value=new int[m];
// Store all values of a^(n*i) of LHS
for (int i = 1, cur = an; i <= n; ++i)
{
if (value[ cur ] == 0)
value[ cur ] = i;
cur = (cur * an) % m;
}
for (int i = 0, cur = b; i <= n; ++i)
{
// Calculate (a ^ j) * b and check
// for collision
if (value[cur] > 0)
{
int ans = value[cur] * n - i;
if (ans < m)
return ans;
}
cur = (cur * a) % m;
}
return -1;
}
// Driver code
public static void main(String[] args)
{
int a = 2, b = 3, m = 5;
System.out.println(discreteLogarithm(a, b, m));
a = 3;
b = 7;
m = 11;
System.out.println(discreteLogarithm(a, b, m));
}
}
// This code is contributed by mits
Python3
# Python3 program to calculate
# discrete logarithm
import math;
def discreteLogarithm(a, b, m):
n = int(math.sqrt (m) + 1);
# Calculate a ^ n
an = 1;
for i in range(n):
an = (an * a) % m;
value = [0] * m;
# Store all values of a^(n*i) of LHS
cur = an;
for i in range(1, n + 1):
if (value[ cur ] == 0):
value[ cur ] = i;
cur = (cur * an) % m;
cur = b;
for i in range(n + 1):
# Calculate (a ^ j) * b and check
# for collision
if (value[cur] > 0):
ans = value[cur] * n - i;
if (ans < m):
return ans;
cur = (cur * a) % m;
return -1;
# Driver code
a = 2;
b = 3;
m = 5;
print(discreteLogarithm(a, b, m));
a = 3;
b = 7;
m = 11;
print(discreteLogarithm(a, b, m));
# This code is contributed by mits
C#
// C# program to calculate discrete logarithm
using System;
class GFG
{
static int discreteLogarithm(int a, int b, int m)
{
int n = (int) (Math.Sqrt (m) + 1);
// Calculate a ^ n
int an = 1;
for (int i = 0; i < n; ++i)
an = (an * a) % m;
int[] value = new int[m];
// Store all values of a^(n*i) of LHS
for (int i = 1, cur = an; i<= n; ++i)
{
if (value[ cur ] == 0)
value[ cur ] = i;
cur = (cur * an) % m;
}
for (int i = 0, cur = b; i<= n; ++i)
{
// Calculate (a ^ j) * b and check
// for collision
if (value[cur] > 0)
{
int ans = value[cur] * n - i;
if (ans < m)
return ans;
}
cur = (cur * a) % m;
}
return -1;
}
// Driver code
static void Main()
{
int a = 2, b = 3, m = 5;
Console.WriteLine(discreteLogarithm(a, b, m));
a = 3;
b = 7;
m = 11;
Console.WriteLine(discreteLogarithm(a, b, m));
}
}
// This code is contributed by mits
的PHP
输出:
3
-1
时间复杂度: O(sqrt(m))
辅助空间: O(sqrt(m))
参考:
http://e-maxx-eng.appspot.com/algebra/discrete-log.html
https://zh.wikipedia.org/wiki/Baby-step_giant-step