ARC139F Many Xor Optimization Problems【组合计数,q-analog】
给定正整数 \(n,m\),考虑所有 \(2^{nm}\) 个长为 \(n\) 且每个元素小于 \(2^m\) 的非负整数序列,求最大子序列异或和之和 \(\bmod 998244353\)。
\(n,m\le 2.5\cdot 10^5\)。
前置知识:q-二项式系数。
参考了 wlzhouzhuan 的题解
枚举所有 \(\mathbb F_2^m\) 的线性子空间,其贡献为生成它的序列个数乘上最大元素。
引理. 长为 \(n\) 的 \(\mathbb F_2^k\) 向量序列生成的线性空间即为 \(\mathbb F_2^k\) 的方案数为 \(\prod_{i=0}^{k-1}(2^n-2^i)\)。
转置一下即为长为 \(k\) 的 \(\mathbb F_2^n\) 向量序列线性无关的方案数。
所以枚举线性子空间的秩 \(k\),为了求出最大元素我们还需要枚举主元,设其从低到高分别为 \(a_1,\cdots,a_k\)。
取线性子空间的标准基底(即每个主元都只有对应向量有值),最大元素即为所有基的异或和,所以最大元素的主元位置都为 \(1\),非主元各有 \(1/2\) 的概率为 \(1\),所以期望值为 \(2^{a_k}+\sum_{i=1}^k2^{a_i-1}-\frac 12\)。而主元对应的线性空间(也即标准基底)数量为 \(\prod_{i=1}^k2^{a_i-(i-1)}\),把这三项乘起来再求和就是答案。
接下来就是纯纯推柿子了。先把 \(2^{-\binom k2}\) 提出来,把期望值的三项拆开分别算。
先看最后一项:\([x^k]\prod_{i=0}^{m-1}(1+2^ix)\),熟练的选手都知道这是 \(2^{\binom k2}\binom mk_2\),不熟练的话对比一下递推公式(?
看中间一项:还要乘上 \(\sum_{i=1}^k2^{a_i}\),一个比较智慧的推法是总的 \(2^m-1\) 减去再选一个的贡献,也就是 \((2^m-1)2^{\binom k2}\binom mk_2-(k+1)2^{\binom{k+1}2}\binom m{k+1}_2\)。
看第一项,还要乘上 \(2^{a_k}\),所以要枚举 \(i=a_k\),也就是下面这个柿子:
这个粉色柿子需要观察一下,实际上是一个经典的吸收恒等式 + 上指标求和。
时间复杂度 \(\color{blue}{\mathcal O(m+\log n)}\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 250003, mod = 998244353;
void qmo(int &x){x += x >> 31 & mod;}
int ksm(int a, int b){
int res = 1;
for(;b;b >>= 1, a = (LL)a * a % mod)
if(b & 1) res = (LL)res * a % mod;
return res;
}
int n, m, pw[N], fac[N], inv[N], ans;
int C(int n, int m){
if(m < 0 || n < m) return 0;
return (LL)fac[n] * inv[m] % mod * inv[n-m] % mod;
}
int main(){
ios::sync_with_stdio(false);
cin >> n >> m; *fac = *pw = 1;
for(int i = 1;i < N;++ i) qmo(pw[i] = (pw[i-1]<<1) - mod);
for(int i = 1;i < N;++ i) fac[i] = fac[i-1] * (pw[i] - 1ll) % mod;
inv[N-1] = ksm(fac[N-1], mod-2);
for(int i = N-1;i;-- i) inv[i-1] = inv[i] * (pw[i] - 1ll) % mod;
for(int k = 1, tmp = 1;k <= n && k <= m;++ k){
tmp = tmp * ((LL)pw[n]+mod-pw[k-1]) % mod;
ans = (ans + ((pw[m+1]-1ll+mod-pw[m-k])*C(m,k)+mod-((LL)k*pw[k]+1)%mod*C(m,k+1)%mod) % mod * tmp) % mod;
}
if(ans & 1) ans += mod;
printf("%d\n", ans >> 1);
}