Not Another Linear Algebra Problem 题解

发布时间 2023-06-13 11:41:46作者: gtm1514

题意:自己看。

首先我们知道我们唯一能找到的题解在 hos_lyric 的代码里。把它放在这里:(由 bikuhiku 提供)

\[\begin{aligned} &U \subseteq \mathbb{F}_p^n, \text{subspace}\\ & a(U) := \#\{ p \in \text{Aut}(\mathbb{F}_p^n) | \text{Ker}(p - \text{id}) = U \}\\ & b(U) := \#\{ p \in \text{Aut}(\mathbb{F}_p^n) | p|_U = \text{id} \}\\ & b(U) = \sum_{V \supseteq U} a(V)\\ \\ & a[\text{dim}(U)] := a(U)\\ & b[\text{dim}(U)] := b(U)\\ & b[i] = \sum_{j\ge i} \begin{bmatrix}n-i\\ n-j\end{bmatrix}_q a[j]\\ & \text{reverse} (a, b)\\ & b[i] = \sum_{j\le i} \begin{bmatrix}i\\ j\end{bmatrix}_q a[j]\\ \\ & b[i] = \prod_{1 \le j \le i}(q^n-q^{n-j})\\ \\ & A(x) := \sum_i \frac{a[i] x^i}{(q;q)_i}\\ & B(x) := \sum_i \frac{b[i] x^i}{(q;q)_i}\\ & B(x) = \frac{A(x)}{(x;q)_{\infty}}\\ & A(x) = B(x) \times (x;q)_{\infty}\\ \\ & B(x) = \sum_i (-1)^i q^{\binom{n}{2}- \binom{n-i}{2}} x^i\\ & x B(x) = \sum_{i\ge 0} (-1)^i q^{\binom{n}{2}-\binom{n-i}{2}} x^{i+1}\\ &=\sum_{i\ge 1}(-1)^{i-1} q^{\binom{n}{2}-\binom{n-i+1}{2}} x^i\\ &=\sum_{i\ge 1}(-1)^i q^{\binom{n}{2}-\binom{n-i}{2}} (-1) q^{i-n} x^i\\ & B(qx) = 1 - q^n x B(x)\\ & A(qx) = B(qx) (qx;q)_{\infty}\\ &=\frac{(1 - q^ x B(x)) (x;q)_{\infty}}{1-x}\\ & (1-x) A(qx) = (x;q)_{\infty} - q^n x A(x)\\ \\ & 提取 [x^i/(q;q)_i]\\ & q^i a[i] - q^{i-1} (1-q^i) a[i-1] = (-1)^i q^{\binom{i}{2}} - q^n (1-q^i) a[i-1] \end{aligned} \]

然后对着这个东西一句一句翻译即可得到正解怎么写)

因为没有官方题解,来一发民间题解。当然写的可能不准,因为作者线代水平十分民科。

首先当然是观察这个形式。肯定要在所有 \(\mathbb F_p^n\) 的所有子空间 \(U\) 上讨论 \(B\) 的每个向量在上边的取值。那么设 \(a_i\)\(i\) 维极大子空间 \(U\),计数里边的 \(\mathbb F_p^n\) 的自同构中在 \(U\) 上为平凡同构的同构个数。另设 \(b_i\)\(\ge i\) 维子空间 \(U\) 计数上述同构的个数(也就是上边的 \(a,b\)),即有显然的式子:枚举 \(i\) 的母空间维数 \(j\),那么剩下的子空间个数为 \(\begin{bmatrix}n-i\\ n-j\end{bmatrix}_q\) (必须在剩下 \(n-i\) 维里选正好 \(n-j\) 维,因为 \(\det B\neq 0\)),即有

\[b[i]=\sum_{j\ge i}\begin{bmatrix}n-i\\n-j\end{bmatrix}_qa[j]\\ \]

这个形式好膈应,翻转 \(a,b\)

\[b[i]=\sum_{j\le i}\begin{bmatrix}i\\j\end{bmatrix}_qa[j] \]

这个形式看上去好多了。(感觉上是可以 q- 二项式反演的,但是我写了写没写出来)

考虑列出 \(a,b\) 的生成函数:

\[A(x)=\sum_i\frac{a_ix^i}{(q;q)_i} \]

\[B(x)=\sum_i\frac{b_ix^i}{(q;q)_i} \]

容易发现上边的式子可以写成卷积形式:

\[B(x)=A(x)(x;q)_{\infty}^{-1} \]

我们需要计算 \(A(x)\),然而卷积是不行的,考虑递推系数。

先看如何算一项 \(b_i\):定了 \(n-i\) 维是恒等置换,那么剩下的随意,即

\[\prod_{j=n-i}^{n-1}q^n-q^j=\prod_{j=1}^iq^n-q^{n-j} \]

将这个代入 \(B(x)\),分子分母拆开,一些 dirty work 可以得到

\[B(x)=\sum_i(-1)^iq^{\binom n2-\binom{n-i}2}x^i \]

这个递推可以直接找 \(xB(x)\)

\[\begin{aligned} xB(x)=&\sum_{i\ge 0}(-1)^iq^{\binom n2-\binom{n-i}2}x^{i+1}\\ =&\sum_{i\ge 1}(-1)^{i-1}q^{\binom n2-\binom{n-i+1}2}x^i\\ =&\sum_{i\ge 1}(-1)^iq^{\binom n2-\binom{n-i}2}(-1)q^{i-n} x^i \end{aligned} \]

那么显然 \(B(qx)=1-q^nxB(x)\)。回代 \(A(x)\) 并提取系数可以直接得到递推式:

\[q^ia_i-q^{i-1}(1-q^i)a_{i-1}=(-1)^iq^{\binom i2}-q^n(1-q^i)a_{i-1} \]

\[a_i=q^{-i}((-1)^iq^{\binom i2}+(q^{i-1}-q^n)(1-q^i)a_{i-1}) \]

这是钦定了 \(i\) 的贡献,对于所有的还要给每个 \(a_i\) 乘上 \(\begin{bmatrix}n\\i\end{bmatrix}_q\)。最后统计答案时,定了 \(i\) 维为恒等置换的 \(B\) 对应的 \(A\) 中这 \(i\) 维可以随意选,即 \(q^{ni}\),而剩下的是定死的,即 \(f(B)=q^{ni}\)。写个光速幂即可。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
using namespace std;
int n,q,mod,ord,jc[10000010],inv[10000010],pw[10000010],cpw[10000010],a[10000010],jcp[10000010],invp[10000010];
int C(int n,int m){
    int rn=n%ord,rm=m%ord;
    n/=ord;m/=ord;
    if(n<m||rn<rm)return 0;
    return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod*jcp[rn]%mod*invp[rm]%mod*invp[rn-rm]%mod;
}
int qpow(int a,int b,int mod){
    int ans=1;
    while(b){
        if(b&1)ans=1ll*ans*a%mod;
        a=1ll*a*a%mod;
        b>>=1;
    }
    return ans;
}
struct node{
    int sq=1<<16,pw[1<<17],gpw[1<<17];
    node(){
        pw[0]=gpw[0]=1;
        for(int i=1;i<sq;i++){
            pw[i]=3ll*pw[i-1]%mod;
        }
        gpw[1]=3ll*pw[sq-1]%mod;
        for(int i=2;i<sq;i++)gpw[i]=1ll*gpw[i-1]*gpw[1]%mod;
    }
    int get(int n){
        return 1ll*gpw[n/sq]*pw[n%sq]%mod;
    }
};
int main(){
    scanf("%d%d%d",&n,&q,&mod);jc[0]=inv[0]=inv[1]=1;
    node P;
    for(int i=2;i<=n;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    for(int i=1;i<=n;i++)jc[i]=1ll*jc[i-1]*i%mod,inv[i]=1ll*inv[i-1]*inv[i]%mod;
    pw[0]=cpw[0]=1;pw[1]=q;
    for(int i=1;i<=n;i++)pw[i]=1ll*pw[i-1]*pw[1]%mod,cpw[i]=1ll*cpw[i-1]*pw[i-1]%mod;
    ord=n+1;
    for(int i=1;i<=n;i++)if(pw[i]==1){
        ord=i;break;
    }
    jcp[0]=invp[0]=1;
    for(int i=1;i<=n;i++)jcp[i]=1ll*jcp[i-1]*(1-pw[i]+mod)%mod;
    invp[n]=qpow(jcp[n],mod-2,mod);
    for(int i=n-1;i>=1;i--)invp[i]=1ll*invp[i+1]*(1-pw[i+1]+mod)%mod;
    a[0]=1;int invpw=qpow(q,mod-2,mod);
    for(int i=1,Inv=1;i<=n;i++){
        Inv=1ll*Inv*invpw%mod;
        a[i]=1ll*(1ll*((i&1)?(mod-1):1)*cpw[i]+1ll*(pw[i-1]-pw[n]+mod)%mod*(1-pw[i]+mod)%mod*a[i-1])%mod*Inv%mod;
    }
    for(int i=0;i<=n;i++)a[i]=1ll*a[i]*C(n,i)%mod;
    int ans=0,ret=qpow(q,n,mod-1);
    if(!ret)ret=mod-1;
    for(int i=0,tmp=1;i<=n;i++){
        ans=(ans+1ll*P.get(tmp)*a[n-i])%mod;
        tmp=1ll*tmp*ret%(mod-1);
    }
    printf("%d\n",ans);
    return 0;
}