专栏文章
有限域结构定理
P3923题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipfng0l
- 此快照首次捕获于
- 2025/12/03 11:13 3 个月前
- 此快照最后确认于
- 2025/12/03 11:13 3 个月前
结构定理一: 设 是一个特征为素数 的有限域,则 中的元素个数为 , 是一个正整数。
证明: 由于 是一个特征为 的有限域,所以 的素子域与 同构。因此 是 的有限扩张,设扩张次数为 ,且 是 在 上的一组基。则 ,所以 中的元素个数为 。
引理一: 如果 在 上不可约,则 是一个域。
证明: 模 同余是 上的一个等价关系。不难证明 是个含幺交换环。
只要证明任意非 元有乘法逆元,设 ,则 ,因为 在 上不可约,所以 ,因此 在 中有乘法逆元。
引理二: 域 上任意一个次数 的多项式 在 上都有分裂域。
证明: 对多项式次数 进行数学归纳:
- 若 ,,则 本身即为分裂域。
- 归纳假设:假设对任意域 及次数 的多项式 ,均存在分裂域。
任取 的一个不可约因子 ,定义 ,则 是个域,且令 ,,所以 是 的根。
在域 上,将 写为 ,。
此时 ,根据归纳假设, 在 上存在分裂域 。可以验证 是 在 上的分裂域。
结构定理二(存在性): 对于任何素数 和任意正整数 ,
总存在一个有限域恰好含有 个元素。
证明: 考虑 上的多项式 。则 ,因此 无重根。
令 为 在 上的分裂域,则 在 中有 个不同的根。
设 为根的集合,则 ,,下面证明 是域。
- 加法封闭:,
- 乘法封闭:,。
- 加法逆元:,若 则 ,否则
- 乘法逆元:,
因此 构成域。
因为 是 的根集合,同时可证明 ,因此 是 的分裂域,即 。
所以 是阶为 的域。
有限域上元素的表示
设 ,,只要找到 上一个 次不可约多
项式 , 就有 。
其中加法和乘法都是模 的多项式运算,乘法逆元可以通过扩展欧几里得算法求出。
代码实现时随机一个 次多项式,暴力判断是否可约即可。
参考代码:
CPP#include<bits/stdc++.h>
using namespace std;
mt19937 rnd(0x66ccff);
typedef vector<int> poly;
int m,P,n,inv[1005];
#define deg(f) (f.size()-1)
#define F(x) (poly{x})
inline poly operator +(poly a,poly b){
if(deg(a)<deg(b))swap(a,b);
for(int i=0;i<=deg(b);++i)a[i]=(a[i]+b[i])%P;
while(deg(a)&&!a.back())a.pop_back();
return a;
}
inline poly operator -(poly a,poly b){
for(int i=0;i<=deg(b);++i)if(b[i])b[i]=P-b[i];
return a+b;
}
inline poly operator *(poly a,poly b){
poly c(deg(a)+deg(b)+1,0);
for(int i=0;i<=deg(a);++i)for(int j=0;j<=deg(b);++j)
c[i+j]=(c[i+j]+a[i]*b[j])%P;
while(deg(c)&&!c.back())c.pop_back();
return c;
}
inline pair<poly,poly> operator /(poly a,poly b){
if(deg(a)<deg(b))return {F(0),a};
if(!deg(a))return {F(a[0]*inv[b[0]]%P),F(0)};
int o=1ll*a.back()*inv[b.back()]%P;
poly c(deg(a)-deg(b)+1,0);
c.back()=o;
a=a-c*b;
tie(a,b)=a/b;
return {a+c,b};
}
poly exgcd(poly a,poly b,poly &X,poly &Y){
auto [c,d]=a/b;
if(d==F(0)){
X=F(0),Y=F(inv[b.back()]);
b=b*F(inv[b.back()]);
return b;
}
poly g=exgcd(b,d,Y,X);
Y=Y-c*X;
return g;
}
bool check(){
int x=m;
if(x==1)return false;
P=2;
while(x%P!=0)++P;
while(x%P==0)x/=P,++n;
return x==1;
}
int ptoi(poly a){
int b=0;
for(int i=deg(a);~i;--i)b=b*P+a[i];
return b;
}
poly itop(int b){
if(!b)return F(0);
poly a;
while(b)a.push_back(b%P),b/=P;
return a;
}
bool find(){
poly f(n+1),X,Y,g;
f[n]=1;
for(int i=0;i<n;++i)f[i]=rnd()%P;
for(int i=1;i<m;++i){
g=exgcd(f,itop(i),X,Y);
if(g!=F(1))return false;
}
for(int i=0;i<m;++i)for(int j=0;j<m;++j){
X=itop(i),Y=itop(j);
g=X+Y;
tie(X,Y)=g/f;
printf("%d%c",ptoi(Y)," \n"[j==m-1]);
}
for(int i=0;i<m;++i)for(int j=0;j<m;++j){
X=itop(i),Y=itop(j);
g=X*Y;
tie(X,Y)=g/f;
printf("%d%c",ptoi(Y)," \n"[j==m-1]);
}
return true;
}
int main(){
scanf("%d",&m);
if(!check())return puts("-1"),0;
puts("0");
inv[1]=1;
for(int i=2;i<P;++i)inv[i]=(P-P/i)*inv[P%i]%P;
while(!find());
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...