试试这个:
#include <iostream>
#include <functional>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int inverse_mod_26(int d)
{
// We're not going to use Euclidean Alg. or
// even Fermat's Little Theorem, but brute force
int base = 26, inv = 1;
while ( (inv < base) &&
(((d * ++inv) % 26) != 1)) {}
return inv;
}
int main(int argc, char **argv)
{
Matrix2d m, minv;
int inv_factor;
m << 14, 3, 15, 0;
double mdet = m.determinant();
minv = mdet * m.inverse();
transform(&minv.data()[0], &minv.data()[4], &minv.data()[0],
[](double d){ return static_cast<int>(d) % 26;});
if ((static_cast<int>(mdet) % 26) == 1) { // no further modification}
else
{
inv_factor = inverse_mod_26(std::abs((m * minv)(0,0)));
if (inv_factor == 26)
{
cerr << "No inverse exists!" << endl;
return EXIT_FAILURE;
}
transform(&minv.data()[0], &minv.data()[4], &minv.data()[0],
[=](double d){ return static_cast<int>(d) * inv_factor;});
}
cout << "m = " << endl << m << endl;
cout << "minv = " << endl << minv << endl;
cout << "(m * minv) = " << endl << m * minv << endl;
return 0;
}
这是一个 2x2 的情况,以 26 为基数,但可以轻松修改。该算法依赖于修改正常矩阵逆,如果您愿意,可以很容易地解释。如果您的原始矩阵具有与 26 不互质的行列式(在正常意义上);即,如果GCD(det(m), 26) != 1,那么它不会有逆。
提示:为了避免这个问题以及上面的 else 子句,用三个任意字符填充您的字典,将大小设置为 29,这是素数,并且可以轻松满足上面的 GCD 属性。