已知给定素数和乘法循环群的生成元g,则对任意的,存在正整数,满足。而求解对应的x就是所谓的离散对数问题,当q较大时,该问题通常比较困难。一种较好的求解方法是大步小步算法。
根据已学过的大步小步算法,编程求解下述两个离散对数问题,并输出解。
- 快速幂算法
long long Quick_Multiply(long long a, long long b, long long c) //快速积
{
long long ans = 0, res = a;
while (b)
{
if (b & 1)
ans = (ans + res) % c;
res = (res + res) % c;
b >>= 1;
}
return (long long)ans;
}
long long Quick_Power(long long a, long long b, long long c) //快速幂
{
long long ans = 1, res = a;
while (b)
{
if (b & 1)
ans = Quick_Multiply(ans, res, c);
res = Quick_Multiply(res, res, c);
b >>= 1;
}
return ans;
}
2.大步小步算法
long long bsgs(long long g, long long Q, long long p)
{
long long s = (long long)floor(sqrt(p));
long long x, r, t;
int* a0 = new int[MAX];
int* b0 = new int[MAX];
for (long long r = 0; r < s; r++)
{
long long temp = Q * Quick_Power(g, r, p);
a0[r] = temp % p;
}
for (long long t = 1; t <= s; t++)
{
long long temp = Quick_Power(g, t * s, p);
b0[t-1] = temp;
}
long long i, j;
int flag = 0;
for (i = 0; i < s; i++)
{
for (j = 0; j < s; j++)
{
if (a0[i] == b0[j])
{
r = i;
t = j+ 1;
flag = 1;
break;
}
}
if (flag)
break;
}
if (i == s && j == s)
{
return -1;
}
x = t * s - r;
delete[] a0;
delete[] b0;
return x;
}
3.测试代码
int main()
{
long long g, Q, q;
long long x;
while(true)
{
cout << "请输入g、Q、q:(输入-1结束程序):";
cin >> g ;
if (g == -1)
break;
cin >> Q >> q;
x = bsgs(g, Q, q);
if(x!=-1)
{
cout << g << " ^ " << x << " = " << Q << " ( mod " << q << " )" << endl;
cout << "x = " << x << endl;
}
else
{
cout << "无解" << endl;
}
}
cout << "程序结束......" << endl;
}
4.测试结果
2347 ^ 7739 = 4921 ( mod 27943 )
3409203 ^ 1176343363 = 2038134 ( mod 2021110967 )