[luogu 3923]. 大学数学题

题意

构造一个(n)元有限域,若不存在输出-1,否则域中元素分别用(0, 1, 2, ldots, n - 1)表示,输出加法表和乘法表。
(n leq 343)

题解

我真的会域扩张吗?答:不会
首先,根据一些基础知识,有解当且仅当(n = p ^ d),其中(p in mathbb{P})
其次,根据域扩张的知识,我们要构造的( ext{GF}(p ^ d))一定是由素域( ext{GF}(p))有限扩张而来的。
考察在( ext{GF}(p))下的代数扩张,即假设存在一个( ext{GF}(p)[[x]])下的不可约多项式(f(x)),设(zeta)是这个多项式的一个根,那么( ext{GF}(p ^ d))中的所有元素可以唯一表示成一个多项式

[a_0 + a_1 zeta + a_2 {zeta} ^ 2 + ldots + a_{d - 1} {zeta} ^ {d - 1} (a_i in ext{GF}(p)) ]

(实际上是基(1, zeta, {zeta} ^ 2, ldots, {zeta} ^ {d - 1})的线性组合)
假设我们最后要输出的是这些多项式的加法表和乘法表,那么问题就转化为了找到一个合适的加法运算和乘法运算。
加法就是在域( ext{GF}(p)[[x]])下的多项式加法,乘法就是在域( ext{GF}(p)[[x]])下的多项式乘法。
但是多项式乘法会导致使用的基的大小变大,我们需要把基的大小缩到(d)
考虑可以应用线性组合(f(zeta) = 0)
对于一个多项式,加上或减去(k)倍的(f(zeta))(k in ext{GF}(p)[[x]])),代入(zeta)求值不变。
那么对于一个多项式,如果次数超过了(d - 1),可以将它对(f(zeta))取模,得到的结果是一个次数小于等于(d - 1)的多项式(即基的大小缩到了(d)),并且代入(zeta)后值和原多项式值相等。
现在考虑的是我们输出的是一个数表而不是多项式表,考虑到要把多项式(F)映射到数(f),并且要求这个映射可逆。
如果有办法可以把(zeta)搞出来,那么当然可以直接将(F)映射到(F(zeta))上,这是个同构映射,显然可逆。
但是求(zeta)是不现实的,我们退而求其次,找一个要求不太高的可逆映射即可,比如把多项式(F)的系数看做数(f)(p)进制下每一位的值,可以验证这是可行的。
复杂度(mathcal O(n ^ 2 {log} ^ 2 n))

#include <bits/stdc++.h>
using namespace std;
typedef vector <int> poly;
const int N = 360, M = 10;
const int R[7][8] = {
{1, 7, 11, 19, 37, 67, 131, 283}, // 2, 4, 8, 16, 32, 64, 128, 256
{1, 10, 34, 86, 250, -1, -1, -1}, // 3, 9, 27, 81, 243
{1, 27, 131, -1, -1, -1, -1, -1}, // 5, 25, 125
{1, 50, 345, -1, -1, -1, -1, -1}, // 7, 49, 343
{1, 122, -1, -1, -1, -1, -1, -1}, // 11, 121
{1, 171, -1, -1, -1, -1, -1, -1}, // 13, 169
{1, 292, -1, -1, -1, -1, -1, -1}, // 17, 289
};
int n, id[N], vis[N]; vector <int> pr;
void sieve () {
	for (int i = 2; i < N; ++i) {
		if (!vis[i]) {
			id[i] = pr.size(), pr.push_back(i);
			for (int j = i; j < N; j += i) {
				vis[j] = i;
			}
		}
	}
}
namespace GF {
	int m, p, d, pl[M];
	struct elem {
		int x;
		elem (int _x = 0) : x(_x) {}
		elem compress (const poly &r) {
			x = 0;
			for (int i = d - 1; ~i; --i) {
				x = x * p + r[i];
			}
			return *this;
		}
		poly expand (elem e) {
			poly r(d);
			for (int i = 0; i < d; ++i) {
				r[i] = e.x % p, e.x /= p;
			}
			return r;
		}
		elem operator + (const elem &o) {
			poly F = expand(*this), G = expand(o);
			for (int i = 0; i < d; ++i) {
				F[i] = (F[i] + G[i]) % p;
			}
			return compress(F);
		}
		elem operator * (const elem &o) {
			poly F = expand(*this), G = expand(o), H(d + d, 0);
			for (int i = 0; i < d; ++i) {
				for (int j = 0; j < d; ++j) {
					H[i + j] = (H[i + j] + F[i] * G[j]) % p;
				}
			}
			for (int i = (d - 1) << 1; i > d - 1; --i) {
				H[i] = -H[i] % p, H[i] += H[i] >> 31 & p;
				for (int j = 1; j <= d; ++j) {
					H[i - j] = (H[i - j] + H[i] * pl[d - j]) % p;
				}
			}
			return compress(H);
		}
	} ;
	void get_poly () {
		for (int i = 0, x = R[id[p]][d - 1]; i <= d; ++i) {
			pl[i] = x % p, x /= p;
		}
	}
} using namespace GF;
int main () {
	sieve();
	cin >> n, m = n, p = vis[n];
	for (int x = n; x != 1; x /= p, ++d) {
		if (x % p != 0) {
			n = 1;
			break;
		}
	}
	if (n == 1) {
		puts("-1");
	} else {
		puts("0");
		get_poly();
		for (int i = 0; i < m; ++i) {
			for (int j = 0; j < m; ++j) {
				printf("%d%c", ((elem)i + (elem)j).x, j < n - 1 ? ' ' : '
');
			}
		}
		for (int i = 0; i < n; ++i) {
			for (int j = 0; j < n; ++j) {
				printf("%d%c", ((elem)i * (elem)j).x, j < n - 1 ? ' ' : '
');
			}
		}
	}
	return 0;
}
/*
4  : x ^ 2 + x     + 1             (111)2       = 7
8  : x ^ 3 + x     + 1             (1011)2      = 11
9  : x ^ 2 + 1                     (101)3       = 10
25 : x ^ 2 + 2                     (102)5       = 27
27 : x ^ 3 + 2x    + 1             (1021)3      = 34
81 : x ^ 4 + x     + 2             (10012)3     = 86
121: x ^ 2 + 1                     (101)11      = 122
125: x ^ 3 + x     + 1             (1011)5      = 131
169: x ^ 2 + 2                     (102)13      = 171
128: x ^ 7 + x     + 1             (10000011)2  = 131
243: x ^ 5 + 2x    + 1             (1000021)3   = 250
256: x ^ 8 + x ^ 4 + x ^ 3 + x + 1 (100011011)2 = 283
343: x ^ 3 + 2                     (1002)7      = 345
*/
原文地址:https://www.cnblogs.com/psimonw/p/11832697.html