社论 22.10.4 同态计数 题解

Problem

同态计数

Mn(Fp) 表示模 p 意义下全体 n 阶矩阵的集合。

一个映射 f:RR 称为同态,当且仅当 X,YR,f(X+Y)=f(X)+f(Y)  f(X×Y)=f(X)×f(Y)

两个映射 f,g 是不同的,当且仅当  x,f(x)g(x)

给定 n,p,保证 p 是素数。你需要计算出 Mn(Fp) 上同态映射的数量。答案对 109+7 取模。

n1e7,p109

M1(F7) 上的同态映射只有两种:f(x)=xf(x)=0。因此答案为 2。

Solution

首先我们根据一些基础的线代知识,对于一个可逆的矩阵 C,形如 fC(x)=C1XC 的映射定是同态映射。

证明

fC(XY)=C1XYC=C1XCC1YC=(C1XC)(C1YC)=fC(X)fC(Y)
fC(X+Y) 平凡,证明从略。

随后我们有断言:所有同态要么是平凡同态 f(X)=0,要么是形如 fC 的映射。

题解对于这个断言的证明:

如果你懂很多代数

注意到 Mn(Fp) 是单环,那么它上面的同态只能是平凡同态和同构,再注意到它是一个中心单代数,根据 Skolem-Noether 定理它的同构必然是内的。

如果你只懂微小的代数

我们当然只处理不平凡的同态,取 Zp上的 n 维向量空间 V,取定一组基,把矩阵解释成线性算子。我们看 Pi=f(Ei,i) ,不难验证 V=iPiV ,并且 Pi 是投影算子,于是 dimPiV=1。设 P1V=<A1>Ai=f(Ei,1)A1,把 Ai 们在基下的坐标取成列向量,再把列向量排成行构成一个矩阵 AA1 即为所求矩阵。

如果有人看到这里就已经会了那您nb。反正我是不会。

于是我们对“很多”的部分进行一个人话的转录。

第一句:Mn(Fp) 是单环。
单环是没有非平凡理想的环。简单来说,从单环中任选一个元素 r,能满足对其中任意元素左/右乘 r 得到结果还属于其自身的子群只有该单环本身。

第二句:单环上的同态只能是平凡同态或同构。
同态的定义是保持环上两个运算结构的映射。同构的定义是同态双射。
对于同态 f:RR,由于这是一个自同态,因此若任意元素不在像空间或原像空间内就不满足同态性质了。因此这个同态是满射。由于这是单环上的同态,因此其对应运算保持矩阵乘法的结构,因此不存在两个不同的原像使得他们的像相同。因此这个同态是单射。
这也就证明了非平凡自同态是自同构。因此问题归约到所有非平凡自同构的形态问题。

第三句:Mn(Fp) 是一个中心单代数。
Mn(Fp) 是一个矩阵环,因此它是一个矩阵代数。矩阵代数的外推是中心单代数,因 此Mn(Fp) 是一个中心单代数。

第四句:根据 Skolem-Noether 定理,断言成立。
Skolem-Noether 定理:域上的 n×n 矩阵代数上的自同构为内自同构。
由于第三句的证明,我们能断言 Mn(Fp) 上的自同构为内自同构。
内自同构是以共轭方式给出的定义。群 G 的一个自同构,如果是 G 内的元素的共轭作用,便称为内自同构。由 gG 的共轭作用给出的内自同构 fg(x)=gxg1。取 g=C1 得到 f(X)=C1XC

由定义,有所有内自同构形如 fC。由第二句的结论,有所有非平凡同态形如 fC
因此我们证明了断言。

对于“微小”的部分,不要去碰它。
某些人的心态已经被读明白这段话而搞崩了。

接下来我们只需要求不同的形如 fC 的同态的个数,取模后加上平凡同态就是答案。

注意到  X,C1XC=A1XA。因此两边左乘 A 右乘 C1 得到  X,AC1X=XAC1。因此 AC1 与所有矩阵乘积可交换,此性质表明其只有对角线有相同元素,即其是一个纯量阵。因此 A=λC
因此 fA=fCA=λC。于是同态个数就是全体 n 阶可逆矩阵 GLn 的个数除以系数种类 (p1)。注意到矩阵可逆的充要条件是矩阵满秩。于是考虑求得满秩 n×n 矩阵的个数。
Zp (模 p 意义下整数集合)上的 n 维向量空间 V。从中取矩阵第一行(可视作行向量) a1,共有 pn1 种取法(除去全零向量)。第二行可以取 V \{a1} 中的所有向量,取法有 pnp 种(除去全零向量和先前取出的向量能表出的 p1 个向量)。以此类推取完 n 行,这部分的答案可写作 i=0n1(pnpi)

因此最终答案即为

i=0n1(pnpi)p1+1

code
#include <bits/stdc++.h>
int n, p, sq[10000007], mod = 1e9 + 7;

typedef long long ll; typedef __int128 lll;
struct FastMod { int m; ll b; void init(int _m) { m = _m; b = ((lll)1<<64) / m; } int operator() (ll a) {ll q = ((lll)a * b) >> 64; a -= q * m; if (a >= m) a -= m; return a; } } Mod;
int add(int a, int b) { return (a += b) >= mod ? a - mod : a; } int mul(int a, int b) { return Mod(1ll * a * b); } template <typename ...Args> int mul(int a, Args ...b) { return mul(a, mul(b...)); }

int qp(int a, int b = mod - 2) { 
    int ret = 1; 
    while (b) { 
        if (b & 1) ret = mul(ret, a); 
        a = mul(a, a); 
        b >>= 1; 
    } return ret; 
}

signed main() {
    std::cin >> p >> n; int ans = 1;
    sq[0] = 1; Mod.init(mod);
    for (int i = 1; i <= n; i++) sq[i] = mul(sq[i-1], p);
    for (int i = 0; i < n; i++) ans = mul(ans, sq[n] - sq[i] + mod);
    std::cout << add(mul(ans, qp(p-1)), 1);
}
posted @   joke3579  阅读(616)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示