有限域结构定理
C1942huangjiaxu · · 题解
结构定理一: 设
证明: 由于
引理一: 如果
证明: 模
只要证明任意非
引理二: 域
证明: 对多项式次数
- 若
n=1 ,f(x)=a(x-\alpha) ,则F 本身即为分裂域。 - 归纳假设:假设对任意域
K 及次数\lt n 的多项式g(x)\in K[x] ,均存在分裂域。
任取
在域
此时
结构定理二(存在性): 对于任何素数
证明: 考虑
令
设
- 加法封闭:
\forall \alpha,\beta \in S ,(\alpha+\beta)^{p^n}=\alpha^{p^n}+\beta^{p^n}=\alpha+\beta - 乘法封闭:
\forall \alpha,\beta \in S ,(\alpha\beta)^{p^n}=\alpha^{p^n}\beta^{p^n}=\alpha\beta 。 - 加法逆元:
\forall \alpha \in S ,若p=2 则\alpha =-\alpha ,否则(-\alpha)^{p^n}=(-1)^{p^n}\alpha^{p^n}=-\alpha - 乘法逆元:
\forall \alpha \in S ,(\alpha^{-1})^{p^n}=(\alpha^{p^n})^{-1}=\alpha^{-1}
因此
因为
所以
有限域上元素的表示
设
其中加法和乘法都是模
代码实现时随机一个
参考代码:
#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;
}