zoukankan      html  css  js  c++  java
  • 一种简单方法构造 n 元有限域

    最近《高等代数》刚学了域的概念,突然想起曾经这么的一个问题,找了许久才找到以前用的那种方法,觉得还是挺有启发性的。

    那么问题就是给定正整数 (nge 2),需要构造一个 (n) 元有限域,也就是说我们给出一个 (n imes n) 的加法表和 (n imes n) 的乘法表。

    不难得知,难点在于选择恰当的运算规则使得乘法逆存在。

    Case 1

    (n) 是质数,那么有如下构造 (mathbb{Z}_p=S={0,1,2,dots,p-1})

    • (forall a,bin S,aoplus b=a+b-[dfrac{a+b}{p}] imes p in S)
    • (forall a,bin S,aotimes b=ab-[dfrac{ab}{p}] imes p in S)

    根据费马小定理,乘法逆可以定义为 (a^{-1}=a^{p-2})

    Case 2

    (n) 含有至少两个质因子。我们断言,这种情况下不存在 (n) 元的有限域。

    Case 3

    剩余的情况,则 (n=p^k),其中 (pin prime,kge 2)

    我们构造多项式

    [f(x)=sum_{i=0}^{k-1}a_ix^i quad (a_i=0,1,2,dots,p-1) ]

    即构造一个定义系数在 (mathbb{Z}_p) 上的度数不超过 (p-1) 的多项式域 (G),而该域的大小恰好为 (p^k)

    我们可以通过 (p) 进制分解(或其他方式)将 (S={0,1,2,dots,n-1})(G) 形成双射。

    现在我们定义 (G) 的运算,考虑到需要保证其度数不超过 (p-1),我们先取一个系数在 (mathbb{Z}_p) 上的度数为 (p) 的不可约多项式 (M(x))

    • (forall f(x),g(x)in G,f(x)oplus g(x)=f(x)+g(x) in S)
    • (forall f(x),g(x)in G,r(x)=f(x)otimes g(x)=f(x)g(x)mod M(x)),即多项式的带余除法结果,(delta(r(x))<delta(M(x))=p),故 (r(x)in S)

    与此同时,多项式 (I(x)=1) 即为乘法幺元。
    由于 (M(x)) 是不可约多项式,可以证明任取一个 (G) 中的元素 (f),均存在一个 (gin G) 使 (f(x)otimes g(x) =I(x))。(存在多项式乘法逆)

    需要注意,例如在 (mathbb{Z}_2) 上,(x^2+1) 并不是不可约多项式,因为 ((x+1)(x+1)=x^2+1);而 (x^2+x+1) 满足;在 (mathbb{Z}_3) 上,可取 (x^2+x+2) 为不可约多项式。

    至此,我们完成了构造。

    附1

    实现上述得到的一个 (9) 元域(加法表 和 乘法表)

    0 1 2 3 4 5 6 7 8
    1 2 0 4 5 3 7 8 6
    2 0 1 5 3 4 8 6 7
    3 4 5 6 7 8 0 1 2
    4 5 3 7 8 6 1 2 0
    5 3 4 8 6 7 2 0 1
    6 7 8 0 1 2 3 4 5
    7 8 6 1 2 0 4 5 3
    8 6 7 2 0 1 5 3 4

    0 0 0 0 0 0 0 0 0
    0 1 2 3 4 5 6 7 8
    0 2 1 6 8 7 3 5 4
    0 3 6 7 1 4 5 8 2
    0 4 8 1 5 6 2 3 7
    0 5 7 4 6 2 8 1 3
    0 6 3 5 2 8 7 4 1
    0 7 5 8 3 1 4 2 6
    0 8 4 2 7 3 1 6 5

    附2

    参考代码(手动寻找不可约多项式,只能处理少数固定大小的 (n)

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    typedef vector<int> poly;
    int n, p, k;
    poly d, av;
    vector<poly> a;
    
    void dfs(int x)
    {
    	if(x < 0)
    	{
    		a.emplace_back(av);
    		return;
    	}
    	for(int j = 0; j < p; ++j)
    		av[x] = j, dfs(x - 1);
    }
    
    int calc(const poly& a)
    {
    	int res = 0;
    	for(int i = 0, q = 1; i < k; ++i)
    		res += a[i] * q, q = q * p;
    	return res;
    }
    
    poly operator + (const poly&a, const poly&b)
    {
    	poly c = a;
    	for(int i = 0; i < k; ++i) c[i] = (a[i] + b[i]) % p;
    	return c;
    }
    
    poly operator * (const poly&a, const poly&b)
    {
    	poly c(k + k - 1);
    	for(int i = 0; i < k; ++i)
    		for(int j = 0; j < k; ++j)
    			c[i + j] += a[i] * b[j];
    	for(int i = 2 * k - 2; i >= k; --i)
    		for(int j = 0; j < k; ++j)
    			c[i + j - k] -= c[i] * d[j];
    	for(int i = 0; i < k; ++i)
    		c[i] = (c[i] % p + p) % p;
    	c.resize(k);
    	return c;
    }
    
    int main()
    {
    	freopen("1.out","w",stdout);
    	scanf("%d", &n);
    	for(int x = 2; x <= n; ++x)
    		if(n % x == 0)
    		{
    			p = x;
    			int y = n;
    			while(y % x == 0) y /= x, ++k;
    			if(y != 1)
    				return puts("-1"), 0;
    			break;
    		}
    	puts("0");
    	if(k == 1)
    	{
    		for(int x = 0; x < n; ++x)
    			for(int y = 0; y < n; ++y)
    				printf("%d%c", (x + y) % n, " 
    "[y + 1 == n]);
    		for(int x = 0; x < n; ++x)
    			for(int y = 0; y < n; ++y)
    				printf("%d%c", (x * y) % n, " 
    "[y + 1 == n]);
    		return 0;
    	}
    	if(k == 2)
    	{
    		if(p != 5 && p != 11)
    			d = poly{-1, 1, 1};
    		else
    			d = poly{1, 1, 1};
    	}
    	else if(k == 3)
    	{
    		if(p == 3)
    			d = poly{-1, 0, 1, 1};
    		else
    			d = poly{1, 1, 0, 1};
    	}
    	else if(k == 4)
    		d = poly{1, 1, 1, 1, 1};
    	else if(k == 5)
    		d = poly{1, 1, -1, -1, 0, 1};
    	else if(k == 7)
    		d = poly{1, 1, -1, -1, 0, 0, 0, 1};
    	else if(k == 8)
    		d = poly{1, 1, -1, 0, 0, 0, 0, -1, 1};
    	av = poly(k);
    	dfs(k - 1);
    	for(int x = 0; x < n; ++x)
    		for(int y = 0; y < n; ++y)
    			printf("%d%c", calc(a[x] + a[y]), " 
    "[y + 1 == n]);
    	for(int x = 0; x < n; ++x)
    		for(int y = 0; y < n; ++y)
    			printf("%d%c", calc(a[x] * a[y]), " 
    "[y + 1 == n]);
    }
    
  • 相关阅读:
    ORA12560: TNS: 协议适配器错误的问题
    ibatis代码生成工具abator使用全过程
    DbHelper数据操作类
    眼睛有干涩、血丝、怕光,流泪,甚至红肿的现象吗
    Dot.Net代码生成器
    两分钟让你明白什么是ERP
    spring的b/s项目中配置log4j
    十面埋妇
    程序员发展的目标
    标准体重计算查询
  • 原文地址:https://www.cnblogs.com/bestwyj/p/15302519.html
Copyright © 2011-2022 走看看