P3923 大学数学题 题解

· · 题解

混沌邪恶抽代入门题。

题目指路。

阅读本题解前,你需要了解域的定义和其他抽代基础知识。

既然是抽代题那就一个一个结论推吧。

解的存在性

【约定 1】在不易混淆的情况下,将域 (\mathbb{F},+,\times) 记为 \mathbb{F},其加法单位元记为 0,乘法单位元记为 1。本文中的域均为有限域。

【定义 1】(域特征)对于有限域 \mathbb{F},若 \exists p\in N^*,p\times1=0,则称最小的 p\mathbb{F} 的特征。

【结论 1】有限域的特征是质数。

证明:设该有限域为 \mathbb{F},其特征为 p。考虑反证法,设 p=r\times s,1<r,s<p

根据 0=p\times1,带入得到 0=(r\times s)\times 1

根据乘法结合律得到 r\times(s\times 1)=0

r\neq0,故 s\times1=0,与 p 最小矛盾,原命题得证。

【定义 2】(子域与域扩张)若 FP 的非空子集,(P,+,\times) 是域且 (F,+,\times) 是域,则称 (F,+,\times)(P,+,\times) 的子域,(P,+,\times)(F,+,\times) 的扩张,记为 (F,+,\times)\subseteq(P,+,\times)

【定义 3】(扩域的次数)若域 F\subseteq KK 可视为 F- 向量空间,其次数称为扩域的次数,记为 [K:F]

【结论 2】若域 F\subseteq KFq 元有限域,则 Kq^m 元有限域,其中 m=[K:F]

证明:因为 K 可视为 Fm 维向量空间,取 K 一组基向量,每个系数均有 q 种取值,共 m 个系数,乘法原理即得。

【约定 2】我们记 \mathbb{F}_p 为包含 p 个元素的域。显然当 p 为质数时该域存在(模 p 意义下整数域 \mathbb{Z}_p),且其无任何真子域。

【结论 3】(有限域元素个数)一个有限域 \mathbb{F}p^n 个元素,其中 p 为其特征。

证明:显然 \mathbb{F}_p\subseteq\mathbb{F},由结论 2 即得。

读者可以自己搜索 \mathbb{F}_p\subseteq\mathbb{F} 的证明。

由此可以得到:

【结论 4】(有限域的存在性和唯一性)\forall p,n,其中 p 为质数,n 为正整数,有限域 \mathbb{F}_{p^n} 存在且唯一。

该定理的证明与本题无关,在此略去。

综上,我们得到当 n 有且仅有一个质因数时,本题有解。即我们应在 case 3 与 case 14 输出 -1

构造

请注意,有限域 \mathbb{F}_{p^m} 并不是模 p^m 意义下的整环。当且仅当 m=1 时二者同构。

也就是说,如果 n 为质数,直接当称普通模意义下的加法乘法就行。

那么,是质数的幂怎么办?设此时 n=p^m

根据结论 4,任何两个元素数相同的有限域同构。我们只需要找到一个现有的有限域 (\mathbb{F}_{p^m},+,\times),然后构造一个双射 f:\mathbb{F}_{p^m}\to\{0,1,2,\cdots,p^m-1\} 即可。

那么有什么呢?

确实,但是你需要定义向量间的乘法。因为要保证逆元,这是最难的一步。 换一个思路,还有什么同构? 所有系数在 $\mathbb{Z}_p$ 上的次数不超过 $m-1$ 次的多项式! 这下有乘法了,但是乘出来次数会超过 $m-1$。考虑模一个 $m$ 次多项式取模。 我们要保证所有非 $0$ 多项式均存在乘法逆元,这要多项式取模的模数是不可约的多项式。 为什么? 我们可以把多项式视为 $m$ 位的 $p$ 进制数。 若其有乘法逆元,则模数必须是质数,转换成多项式即不可约多项式。 最后的问题就是求不可约多项式了。 首先,如果多项式不首一,我们可以每个系数乘以首项系数逆元,不影响其是否可约。因此只用研究首一多项式。 其次,在求解的时候类似于质数枚举每个 $\lceil\dfrac m 2\rceil$ 阶多项式取模看有没有余项。 最劣的时间复杂度是 $O(n\sqrt nm^2)$,$n$ 这么小显然是跑得很快的。就算枚举到 $m$ 阶的也是 $O(n^2m^2)$,仍然跑得过。 ## 代码 这里给出多项式板子和输出,找不可约多项式的部分就请自己写吧。 ```cpp #include<bits/stdc++.h> #define F(i,a,b) for(int i(a),i##i##end(b);i<=i##i##end;++i) #define R(i,a,b) for(int i(a),i##i##end(b);i>=i##i##end;--i) #define ll long long #define MOD p using namespace std; const int MAXN=30; int n,m,p; inline ll qpow(ll base,int expo){ ll res(1); while(expo){ (expo&1)&&(res=res*base%MOD); base=base*base%MOD,expo>>=1; } return res; } inline void meow(int&t){ t<0&&(t+=MOD); t>=MOD&&(t-=MOD); return; } struct poly{ int num[MAXN]={}; int len=0; inline void init(){ while(!num[len]&&len>0) --len; return; } inline void turn(int t){ while(t) num[len++]=t%MOD,t/=MOD; init(); return; } inline poly operator+(const poly&a)const{ poly res; res.len=max(a.len,len); F(i,0,res.len) res.num[i]=num[i]+a.num[i],meow(res.num[i]); res.init(); return res; } inline poly operator+(const int a)const{ poly res=*this; int&qwq(res.num[0]); qwq+=a; meow(qwq); return res; } inline poly operator-(const poly&a)const{ return a*(-1)+*this; } inline poly operator-(const int a)const{ return *this+(-a); } inline poly operator*(const poly&a)const{ poly x; F(i,0,len) F(j,0,a.len){ int&qwq(x.num[i+j]); qwq+=a.num[j]*1ll*num[i]%MOD; qwq>=MOD&&(qwq-=MOD); } x.len=len+a.len; x.init(); return x; } inline poly operator*(const int a)const{ poly res=*this; F(i,0,len){ int&qwq(res.num[i]); qwq=a*1ll*qwq%MOD; meow(qwq); } return res; } inline bool operator<=(const poly&a)const{ if(len!=a.len) return len<=a.len; R(i,len,0) if(num[i]!=a.num[i]) return num[i]<=a.num[i]; return 1; } inline poly operator<<(const int a)const{ poly res; res.len=a+len; F(i,0,len) res.num[a+i]=num[i]; return res; } inline poly operator%(const poly&a)const{ poly t=*this; while(a<=t){ poly tmp=a*qpow(a.num[a.len],MOD-2)*t.num[t.len]; t=t-(tmp<<(t.len-a.len)); } t.init(); return t; } inline bool check()const{//检查是否不可约 poly x=*this,y; F(i,2,n-1){ poly t; t.turn(i); y=x%t; if(y.len==0&&y.num[0]==0) return 0; } return 1; } inline void output(){ F(i,0,m) cout<<num[i]<<" "; cout<<"\n"; return; } inline int decode(){ int res(0); R(i,len,0) res=res*p+num[i]; return res; } }mod; inline void findmod(){ } int main(){ ios::sync_with_stdio(0); cin.tie(0),cout.tie(0); cin>>n; switch(n){ case 2:case 3:case 19:case 89:case 181:case 233:{ cout<<"0\n"; F(i,0,n-1){ F(j,0,n-1){ cout<<(i+j)%n; j!=n-1&&(cout<<" "); } cout<<"\n"; } F(i,0,n-1){ F(j,0,n-1){ cout<<i*j%n; j!=n-1&&(cout<<" "); } cout<<"\n"; } return 0; break; } case 6:case 143:{ cout<<"-1"; return 0; break; } case 4:{ m=2,p=2; break; } case 8:{ m=3,p=2; break; } case 9:{ m=2,p=3; break; } case 25:{ m=2,p=5; break; } case 121:{ m=2,p=11; break; } case 169:{ m=2,p=13; break; } case 27:{ m=3,p=3; break; } case 128:{ m=7,p=2; break; } case 81:{ m=4,p=3; break; } case 125:{ m=3,p=5; break; } case 243:{ m=5,p=3; break; } case 256:{ m=8,p=2; break; } case 343:{ m=3,p=7; break; } } findmod(); cout<<"0\n"; F(i,0,n-1){ F(j,0,n-1){ poly ii,jj; ii.turn(i),jj.turn(j); cout<<(ii+jj).decode(); j!=n-1&&(cout<<" "); } cout<<"\n"; } F(i,0,n-1){ F(j,0,n-1){ poly ii,jj; ii.turn(i),jj.turn(j); cout<<(ii*jj%mod).decode(); j!=n-1&&(cout<<" "); } cout<<"\n"; } return 0; } ``` 完结撒花 qwq~