做法
有限域 GF(
)上的元素满足加法交换群、线性空间,所以,是和整数有限域上的运算等价的,所以可以直接重载扩展欧几里得来计算多项式的逆元
/*
> Problem:main
> Author: WESTWOOD
> Mail: [email protected]
> Created Time: 2018/6/18 12:58:17
> function:多项式逆元,直接调用整数的扩展欧几里得,然后重载多项式的/*+-运算符
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<bitset>
#pragma warning(disable : 4996)
using namespace std;
using LL = long long;
class polynomial/*多项式*/
{
public:
LL value;
const size_t lenght()const/*获取2进制长度*/
{
LL tmp = value;
int len = 0;
while (tmp) {
len++;
tmp >>= 1;
}
return len;
}
polynomial(LL value) {/*构造函数*/
this->value = value;
}
polynomial operator + (const polynomial &o)/*模2加*/
{
return value ^ o.value;
}
polynomial operator - (const polynomial &o)/*模2除*/
{
return value ^ o.value;
}
polynomial operator * (const polynomial &o)/*模2乘*/
{
polynomial ans = polynomial(0);
polynomial tmp = o;
for (int i = 0;tmp.value;i++, tmp.value >>= 1) {
if (tmp.value & 1) {
ans = ans + polynomial(this->value << i);
}
}
return ans;
}
polynomial operator % (const polynomial &o) {/*模2模*/
size_t len = this->lenght(), leno = o.lenght();
int width = int(len) - int(leno);
polynomial remainder = *this;
polynomial quotient = polynomial(0);
while (width >= 0)
{
if (remainder.value >> (leno + width - 1))
{
quotient.value += (1LL << width);
remainder = remainder - polynomial(o.value << width);
}
width--;
}
return remainder;
}
polynomial operator / (const polynomial &o) {/*模2除*/
size_t len = this->lenght(), leno = o.lenght();
int width = int(len) - int(leno);
polynomial remainder = *this;
polynomial quotient = polynomial(0);
while (width >= 0)
{
if (remainder.value >> (leno + width - 1))
{
quotient.value += (1LL << width);
remainder = remainder - polynomial(o.value << width);
}
width--;
}
return quotient;
}
friend ostream &operator<<(ostream &os, const polynomial&o);
};
pair <LL, LL> exgcd(LL a, LL b)/*整数的扩展扩展欧几里得*/
{
if (b == 0)
return { 1,0 };
auto factor = exgcd(b, a%b);
auto &x = factor.first, &y = factor.second;
auto xp = y, yp = x - a / b * y;
return { xp,yp };
}
pair <polynomial, polynomial> exgcd(polynomial a, polynomial b)/*多项式的扩展扩展欧几里得*/
{
auto tmp = a / b;
if (b.value == 0)
return { polynomial(1),polynomial(0) };
auto factor = exgcd(b, a%b);
auto &x = factor.first, &y = factor.second;
auto xp = y, yp = x - (a / b * y);
return { xp,yp };
}
const polynomial GF8 = polynomial((1 << 8) + (1 << 4) + (1 << 3) + (1 << 1) + 1);
ostream &operator<<(ostream &os, const polynomial&o) {
auto value = o.value;
if (value == 0)
{
os << 0;
return os;
}
bool flag = false;
for (int i = 0;value;i++, value >>= 1) {
if (value & 1) {
if (flag)
os << "+";
flag = true;
if (i)
os << "x^" << i;
else
os << 1;
}
}
return os;
}
int main()
{
if (fopen("in.txt", "r") != NULL)
{
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
}
cout << "3在mod11下的逆元:" << exgcd(3, 11).first << endl;
cout << "密码学书本83页书上的样例:\n";
cout << (polynomial((1 << 8) + (1 << 6) + (1 << 4) + (1 << 3) + (1 << 2)) % GF8).value << endl;
cout << (polynomial((1 << 6) + (1 << 4) + (1 << 2) + (1 << 1) + 1)*polynomial((1 << 7) + (1 << 1) + 1) % GF8) << endl;
cout << (polynomial((1 << 7) + (1 << 5) + (1 << 3) + (1 << 2) + (1 << 1)) % GF8) << endl;
cout << (polynomial((1 << 8) + (1 << 6) + (1 << 4) + (1 << 3) + (1 << 2)) % GF8) << endl;
cout << "0x02在GF8下的逆元:" << exgcd(polynomial(2), GF8).first << endl;
return 0;
}