超几何变换
先来看一些封闭形式,比如和式 k⩽m∑(kn) 对应于
(mn)F(1,−mn−m+1∣∣∣∣∣∣ −1),n⩾m⩾0
将上式进行化简,等价于 (mn)k∑(kn−m+k)(km)=k∑m!(n−m)!n!⋅(m−k)!(n−m+k)!m!(n−m)!
进一步化简, k∑(m−kn)=k′⩽m∑(k′n),证明完毕
反射定律
(1−z)a1F(a,bc∣∣∣∣∣∣ 1−z−z)=F(a,c−bc∣∣∣∣∣∣ z)
根据二项展开,不难写出左边等于
k⩾0∑ckakbk⋅k!(−z)k⋅m⩾0∑(mk+a+m−1)zm
令 k+m=n,求和可以写成,n⩾0∑znk⩾0∑ckk!akbk(−1)k(n−kn+a−1)
对 zn 的系数展开
(a−1)!c(c+1)⋯(c+k−1)⋅k!(a−1)!a(a+1)⋯(a+k−1)⋅b(b+1)⋯(b+k−1)⋅(−1)k(n−k)!(a+k−1)!(n+a−1)!
(a+k−1)! 可以约去,将 (−1)k 开始的后半部分做一个变形
(−1)k(n−k)!(n−k+1)(n−k+2)⋯n(n+a−1)!⋅(n−k+1)(n−k+2)⋯n
综上所述,可以将原式化简成
ckk!bk⋅n!(a−1)!(n+a−1)!⋅(−n)k=(nn+a−1)F(a,b,−nc,a∣∣∣∣∣∣ 1)
根据范德蒙卷积,多项式的超几何表示这一节内容的 (3),原式为 n!ancn(c−b)n
库默尔公式和反射定律
令 c=1+b−a 代入反射定律中,可以得到
2−aF(a,1−a1+b−a∣∣∣∣∣∣ 21)=F(a,b1+b−a∣∣∣∣∣∣ −1)=b!(b/2)!(b−a)b/2
令 a=−n 就可以得到一个新的恒等式
k⩾0∑(1+b+n)k(−n)k(1+n)kk!2−k=k∑(kn)(2−1)k(kn+k)/(kn+b+k)
=2−nb!(b/2+n)!(b/2)!(b+n)!
其他一些恒等式
k⩽m∑(km+k)2−k=2m,令 k′=m−k 代入,可以得到
k⩾0∑(m−k2m−k)2k=2m,写成超几何形式,令 tktk+1=(k−2m)(k+1)2(k−m)(k+1)
(m2m)F(1,−m−2m∣∣∣∣∣∣ 2)=22m
但这个形式并不是标准形式,因为下参数 −2m 被禁止的
但 (m2m)F(1,−m−2m∣∣∣∣∣∣ 2)=22m 表示 k⩾0∑(m−k2m−k)2k
我们想要令 k>m 的项都为 0(二项式下指标 <0 时值都为 0)
注意到上参数,(−m)k 形式是 (⋯(−m+k−1)(−m+k)⋯),在 k>m 的时候,一定包含 0
所以对于 k>m 的项,F 展开分子为 0
为了使极限有良好定义,对超几何函数 F 的下参数取极限,具体来说
(m2m)ϵ→∞limF(1,−m−2m+ϵ∣∣∣∣∣∣ 2)=22m,m⩾0
这样,分子在 k>m 时候为 0,分母 (−2m)k 在 k>2m 时才为 0,这样以来,极限刚好给出了良好的定义
(1)
(m2m)ε→∞limF(1,−m−2m+ε∣∣∣∣∣∣ 2)=22m,m⩾0
根据 (1) 可以推出其他恒等式,在反射定律中,令 z=2,a=−m,b=1,c=−2m+ε
(−1)mε→0limF(1,−m−2m+ε∣∣∣∣∣∣ 2)=ε→0limF(−m,−2m−1+ε−2m+ε∣∣∣∣∣∣ 2)
=ε→0limk⩾0∑(−2m+ε)k(−m)k(−2m−1+ε)k⋅k!2k=k⩽m∑(km)(2m)k(2m+1)k(−2)k
这就给出了一个公式
k⩽m∑(km)2m+1−k2m+1(−2)k=(−1)m22m/(m2m),这里用了公式 (1)
=1/(m−1/2),m⩾0
(−1)m22m(2m)(2m−1)⋯2⋅1m!m!=(−1)m⋅m(m−21)(m−22)⋯1⋅21m!m!
=(m(m−1)⋯1)⋅((−21+m)(−23+m)⋯(21))m!m!⋅(−1)m
=1/(m−1/2),m⩾0
微分法
二项级数的部分和恒等式 描述如下
k⩽m∑(km+r)xkym−k=k⩽m∑(k−r)(−x)k(x+y)m−k
两边同时对 y 微分 n 次,然后令 m−n−k 代替 k,很容易得出
k⩾0∑(m−n−km+r)(nn+k)xm−n−kyk=k⩾0∑(m−n−k−r)(nn+k)(−x)m−n−k(x+y)k
展开写成超几何函数形式,左边记 tktk+1,右边记 tk′tk+1′
左边超几何表示 t0F(n−m,n+1n+r+1∣∣∣∣∣∣ −y)
右边超几何表示 t0′F(n−m,n+1n−m−r+1∣∣∣∣∣∣ 1+y)
这里令 ⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧n−m=an+1=−n′n+r+1=cn−m−r+1=a−c−n′+1
另外 t0t0′=(c−1+n′)!⋅(c−a−1)!(c−a−1+n′)!⋅(c−1)!,实际上这里做了替换
{c−a=m+r+1r−1=c+n′−1
于是我们有 t0t0′=cn′(c−a)n′=(−c)n′(a−c)n′
可以推出超几何变换
F(a,−nc∣∣∣∣∣∣ z)=(−c)n(a−c)nF(a,−n1−n+a−c∣∣∣∣∣∣ 1−z)
超几何级数的微分
dzdF(a1,⋯,amb1,⋯,bn∣∣∣∣∣∣ z)=k⩾1∑b1k⋯bnk(k−1)!a1k⋯amkzk−1
作代换,令 k−1=k′,从而有
=k+1⩾1∑b1k+1⋯bnk+1(k)!a1k+1⋯amk+1zk=k⩾0∑b1(b1+1)k⋯bn(bn+1)k(k)!a1(a1+1)k⋯am(am+1)kzk
=b1⋯bna1⋯amF(a1+1,⋯,am+1b1+1,⋯,bn+1∣∣∣∣∣∣ z)
dzdF(a1,⋯,amb1,⋯,bn∣∣∣∣∣∣ z)=b1⋯bna1⋯amF(a1+1,⋯,am+1b1+1,⋯,bn+1∣∣∣∣∣∣ z)
微分算子
记算子 ϑ=zdzd
容易推出
dzdF(a1,⋯,amb1,⋯,bn∣∣∣∣∣∣ z)=zk⩾1∑b1k⋯bnk(k−1)!a1k⋯amkzk−1=k⩾0∑b1k⋯bnk(k)!ka1k⋯amkzk
(ϑ+a1)F(a1,⋯,amb1,⋯,bn∣∣∣∣∣∣ z)=k⩾0∑b1k⋯bnkk!a1(a1+1)ka2k⋯amkzk=a1⋅F(a1+1,a2,⋯,amb1,⋯,bn∣∣∣∣∣∣ z)
(ϑ+b1−1)F(a1,⋯,amb1,⋯,bn∣∣∣∣∣∣ z)=k⩾0∑b1k⋯bnkk!(k+b1−1)a1ka2k⋯amkzk=k⩾0∑(b1−1)kb2k⋯bnkk!(b1−1)a1ka2k⋯amkzk
=(b1−1)F(a1,⋯,amb1−1,b2,⋯,bn∣∣∣∣∣∣ z)
从而有超几何函数微分方程如下
(ϑ+a1)(ϑ+a2)⋯(ϑ+am)F=(a1⋯am)F(a1+1,⋯,am+1b1,⋯,bn∣∣∣∣∣∣ z)
(ϑ+b1−1)⋯(ϑ+bn−1)F=(b1−1)⋯(bn−1)F(a1,⋯,amb1−1,⋯,bn−1∣∣∣∣∣∣ z)
记算子 D=dzd,从而
D(ϑ+b1−1)⋯(ϑ+bn−1)F=(ϑ+a1)(ϑ+a2)⋯(ϑ+am)F(1)
反过来,我们可以从微分方程回到幂级数,不妨设 F(z)=k⩾0∑tkzk 是满足上式子的幂级数
左边,观察 [zk+1] 系数,对于 (ϑ+bn−1)
其系数为 Q(z)=(k+1)tk+1zk+1+(bn−1)tk+1zk+1=(k+bn)tk+1zk+1
D(ϑ+b1−1)⋯(ϑ+bn−1)F(z)=[zk](k+1)(k+b1)⋯(k+bn)tk+1
注意这里对 z 求导,自然会有 (k+1) 这一项
同理,右边为 [zk](k+a1)(k+a2)⋯(k+an)tk
由此 tktk+1=(k+b1)⋯(k+bn)(k+1)(k+a1)(k+a2)⋯(k+am),恰好对于超几何函数表达式
另外,更为普遍的是 2 个上参数的超几何表达式
z(1−z)F′′(z)+(c−z(a+b+1))F′(z)−abF(z)=0(2)
F(z)=F(a,bc∣∣∣∣∣∣ z),根据上式,D(ϑ+c−1)F=(ϑ+a)(ϑ+b)F
其中 (ϑ+c−1)F=zF′(z)+(c−1)F(z),对其求导
左边 F′(z)+zF′′(z)+(c−1)F′(z),右边 zF′(z)+z2F′′(z)+bzF′(z)+azF′(z)+abF(z)
z(1−z)F′′(z)+(c−z(a+b+1))F′(z)−abF(z)=0
如果幂级数 F(z)=k⩾0∑tkzk 满足 (1),那么我们可以有
tktk+1=(k+b1)⋯(k+bn)(k+1)(k+a1)⋯(k+am)
从而 F(z) 就是 t0F(a1,⋯,am; b1,⋯,bn; z)
微分法应用
算子 ϑ=zdzd,所以对于 (1) 而言
右边形式为 αkzkF(k)(z),左边有形式 βkzk−1F(k)(z)
所以微分方程总是可以写成
zn−1(βn−zαn)F(n)(z)+⋯+(β1−zα1)F′(z)−α0F(z)=0(3)
写成全 ϑ 形式,可以用 z 乘以 (1) 的两边
ϑ(ϑ+b1−1)⋯(ϑ+bn−1)F=z(ϑ+a1)⋯(ϑ+am)F
ϑ=(ϑ+1−1) 对应超几何表达式中的 (k+1),(ϑ+bj−1) 对应因子 (k+bj),对应到超几何函数中的 bjk
右边的 z 对应 zk,(ϑ+aj) 对应 ajk
高斯恒等式
高斯恒等式重要的理论依据是基于 2 个上参数的恒等式的超几何表达,即上式 (2)
F⎝⎛2a,2ba+b+21∣∣∣∣∣∣∣ x⎠⎞=F⎝⎛a,ba+b+21∣∣∣∣∣∣∣ 4t(1−t)⎠⎞
先来看右边,令 x=4t(1−t),那么右边形式满足微分方程
x(1−x)dx2d2P+(a+b+21−(a+b+1)x)dxdP−abP=0(2)
作变换,令 x=4t(1−t),那么有 dtdx=4−8t,dxdt=4(1−2t)1
dxdP=dtdP⋅dxdt=4−8t1⋅dtdP
dx2d2P=dxd(4−8t1)⋅dtdP+4−8t1⋅dxd(dtdP)
=dtd(4−8t1)⋅dxdt⋅dtdP+(4−8t)21dt2d2P
=16(1−2t)21dt2d2P+8(1−2t)31dtdP
原式划归如下
41t(1−t)dt2d2P+2(1−2t)t(1−t)dtdP+(a+b+21)(1−4t(1−t))4(1−2t)21dtdP−4(1−2t)2t(1−t)dtdP−abP=0
t(1−t)dt2d2P+(a+b+21−(2a+2b+1)t)dtdP−4abP=0
将高斯恒等式左边代入 (2),恰好和上式一致,问题证毕
超几何恒等式关于二项式系数的推论
先来看一个关于复数 z!1 的定义
z!1=n→∞lim(nn+z)n−z(4)
证明其实很简单,因为 n→∞limnm(n+m)m=1,从而 (nn+m)⋅nmm!=1
令 m=z,即可证明
这是为了引出阶乘加倍公式
x!(x−21)!=(2x)!(−21)!/22x(5)
证明并不难,在 (4) 中分别令 z=−1/2,z=x,z=x−1/2
(−1/2)!=1/(nn−1/2)⋅n−1/2
x!(x−1/2)!=(nn+x)⋅n−x⋅n−x+1/2⋅(nn+x−1/2)
从而有 x!(x−1/2)!(−1/2)!=n→+∞lim(nn+x)(nn+x−1/2)⋅n−2x/(nn−1/2)(1.0)
这里我们要依据两个已知的恒等式,rk(r−21)k=(2r)2k/22k(1.1)
(nn−21)=(n2n)/22n(1.2)
在 (1.1) 中,令 r=n+x, k=n,可以得到 n!(n+x)n⋅n!(n+x−1/2)n=(2n)!(2n+2x)2n⋅n!n!(2n)!⋅2−2n
同时 (1.2) 给出 (nn−1/2)=(n2n)⋅2−2n
(1.0) 化简成 n→∞lim(2n2x+2n)⋅n−2x
同时在 (4) 中令 z=2x, n←2n,综上所得,可知
x!(x−21)!=(2n2n+2x)(−21)!⋅n2x,(2x)!=(2n2n+2x)(2n)2x
相乘即可得到 (5)
超几何级数与二项式还有一个推论
k⩽m∑(nm−k)(km+n+1)(2−1)k=(n(m+n)/2)2n−m[m+n是偶数],m⩾n⩾0(6)
首先不难将二项式写成超几何形式 ε→0lim(nm)F(n−m,−n−m−1+αε−m+ε∣∣∣∣∣∣ 21)
令 α=2,这样可以用高斯恒等式
ε→0lim(nm)F(2(n/2−m/2),2(−n/2−m/2−1/2+ε)−m+ε∣∣∣∣∣∣ 21)=ε→0lim(nm)F(n/2−m/2,−n/2−m/2−1/2+ε−m+ε∣∣∣∣∣∣ 1)
1) m+n 是奇数,m+n=2N−1,那么 F=F(N−m−1/2,−N+ε−m+ε∣∣∣∣∣∣ 1),只要证明 ε→0limF=0
根据欧拉恒等式的推广,F(a,bc∣∣∣∣∣∣ 1)=Γ(c−a)Γ(c−b)Γ(c−a−b)Γ(c),Rc⩾Ra+Rb
此时 Γ(c−b)=Γ(N−m),因为 2N−2m=n−m+1⩽0
所以 N⩽m,因此分母 Γ(N−m)→∞,从而 F→0
2) m+n 是偶数,n−m=−2N,那么令 n=m−2N,可以得到
ε→0limF(−N,N−m−1/2+ε−m+ε∣∣∣∣∣∣ 1)
而这个形式恰好符合恒等式 F(−n,ac∣∣∣∣∣∣ 1)=cn(c−a)n,代入
ε→0limF=mN(N−1/2)N
此时只需要证明 (m−2Nm)(−1/2)!(N−1/2)!⋅m!(m−N)!=(m−2Nm−N)2−2N
在 (5) 中令 x=N,即可证明
(m−2N)!(N)!(m−N)!⋅(2N)!N!⋅(−1/2)!(N−1/2)!=(m−2Nm−N)⋅2−2N
至此,超几何函数只剩下差分,机械求和法两个部分没有讨论了
q-binomial
q-binomial 定义和常用结论
定义
[n]q=i=0∑n−1qi=x→qlim1−x1−xn,[n]!q=i=1∏n[i]q
[mn]q=[m]!q[n−m]!q[n]!q
性质1
[mn]1=(mn)
展开可得
[mn]q=x→qlimi=1∏m1−x1−xii=1∏n−m1−x1−xii=1∏n1−x1−xi=x→qlimi=1∏m(1−xi)i=n−m+1∏n(1−xi)
性质2
[mn]q=[n−mn]q(1)
若 n⩾1,那么有
[mn]q=[m−1n−1]q+qm[mn−1]q(2)
证明,只需要展开即可验证
[m−1n−1]q+qm[mn−1]q
=i=1∏m−1(1−qi)i=n−m+1∏(1−qi)+qm⋅i=1∏m(1−qi)i=n−m∏n−1(1−qi)
=i=1∏m(1−qi)(1−qm)i=n−m+1∏n−1(1−qi)+qm(1−qn−m)i=n−m+1∏n−1(1−qi)
整理得到,i=1∏m(1−qi)i=n−m+1∏n(1−qi)=[mn]q
于此同时,令 m=n−m 还可以得到
[mn]q=qn−m[m−1n−1]q+[mn−1]q
这个式子还有一个组合意义,建立一个纵向 [0,n],横向 [0,m] 的 n×m 的网格
从 (0,0) 开始,每一次往上或者往右走一步,最后到达 (n−m,m)
在所有可能经过的路径中,路径右下方网格数为 cnt,那么 [mn]q 就表示 ∑qcnt
证明用递推,从 (0,0)→(n−m,m) 的路径中,到达 (n−m,m) 的上一步,它的位置要么是 [mn−1]q
要么在 [m−1n−1]q 处
如果从 (n−m−1,m)→(n−m,m) 右下方是没有格子的,直接把方案数 [mn−1]q 加到答案中
如果在 (n−m−1,m−1)→(n−m,m),这个时候我们整体向右平移
即将此时格子的起点向右平移一个单位,那么恰好是从横轴 1 这个位置出发,对应的方案数是 [m−1n−1]q
因为平移的缘故,此时 [m−1n−1]q 恰好和最右边重合,右下方也是没有网格的
只不过平移了 1 个单位,原先的 cnt+=n−m,对应到表达式中,表示成 qn−m[m−1n−1]q
性质3
i=0∏n−1(1+qiy)=i=0∑nq(2i)[in]qyi
证明的过程用数学归纳法
n=1,显然成立
n>1 对 i 归纳,(1+qn−1y)i=0∏n−2(1+qiy)=(1+qn−1y)i=0∑n−1q(2i)[in−1]qyi
=i=0∑n−1q(2i)[in−1]qyi+i=1∑nqn−1q(2i−1)[i−1n−1]qyi
注意到 qn−1=qn−i⋅qi−1,q(2i−1)⋅qi−1=q(2i)
=i=0∑nq(2i)([in−1]q+qn−i[i−1n−1]q)yi=i=0∑nq(2i)[in]qyi
下面来研究其组合意义
注意到展开形式形如 ∑(in)(qi)iyi
其组合意义是,从 n 个元素中选出 i 个元素构成集合 S,∣S∣=i
那么选 i 个元素,该怎么选呢?注意到,编号为 i 之前的元素,即 [0⋯i−1],只有两种可能,选 or 不选
注意到 (2i)=0+1+⋯i−1
由此,可以变形为 (q0⋅qi)⋅(q1⋅qi−1)⋯(qi−1⋅q1)⋅(in)
假设在 [0⋯i−1] 中选了 j 个元素,那么因为 i=0∏n−1(1+qiy) 中有因子 q
所以对答案有 qj 的贡献
(q0q1⋯qi−1)⋅(j=1∏iqj)⋅(in)
其中 (q0q1⋯qi−1) 可以看作编号 [0,i−1] 个元素中选择了 (0,1,⋯,i−1) 个
(j=1∏iqj)⋅(in) 表示编号 [0,i−1] 这些元素没有被选择的个数
[in]q 组合意义就可以表示,在一个长度为 S 的序列中选 i 个元素
编号在 [0,i−1] 的元素没有被选的个数为 j,j∈[1,i],记 j=1∏iqj
[in]q=(in)(j=1∏iqj)
性质4
[kn+m]q=i=0∑kq(n−i)(k−i)[in]q[k−im]q
证明可以根据组合意义
在长度为 n+m 的序列中,取集合 S,∣S∣=k,不妨将其分为 2 部分,左边有 n 个元素,右边有 m 个元素
记左边编号 [0,i−1] 没有被选择的元素个数为 lj,右边 [0,i−1] 没有被选择的部分为 rj
记左边集合为 ∣Sl∣,右边集合为 ∣Sr∣
可以枚举 ∣Sl∣,那么对于特定的 ∣Sl∣
左边的贡献为 ∣Sl∣∏qlj,注意还有 n−∣Sl∣ 个残留元素未被选择
于是右边的贡献为 ∣Sr∣∏qrj+n−∣Sl∣=q∣Sr∣(n−∣Sl∣)⎝⎛∣Sr∣∏qrj⎠⎞
这样对于特定的 ∣Sl∣,其贡献是
q∣Sr∣(n−∣Sl∣)∣Sl∣∏qlj⋅∣Sr∣∏qrj
其中 ∣Sl∣∏qlj 就是 [in]q,∣Sr∣∏qrj 就是 [k−im]q
而 ∣Sl∣=i,∣Sr∣=k−i,代入即可
性质5
[n+1n+m+1]q=[mn+m+1]q=i=0∑mqi[nn+i]q
证明,不断展开性质 2 的递推
[mn]q=[m−1n−1]q+qm⋅[mn−1]q
=qm[mn−1]q+qm−1⋅[m−1n−2]q+⋯=i=0∑mqi[in−(m−i+1)]q
性质6
i=0∏n(1−qix)1=i⩾0∑xi[nn+i]q
证明用数学归纳法,对 n 归纳,n=0 时候显然成立,记原式为 F
根据性质 2,可以有 [ni+n]q=[n−1i+n−1]q+qn[ni+n−1]q,从而
F=i⩾0∑xi[n−1i+n−1]q+qni⩾0∑xi[ni+n−1]q,令 i←i−1
=i⩾0∑xi[n−1i+n−1]q+qn⋅xi⩾0∑xi[ni+n]q
根据归纳假设,可以有
i=0∏n−1(1−qix)1+qnF=F,证毕
性质6非常重要,因为可以转化成为生成函数问题
实际上,[xi]i=0∏n(1−qix)1=[nn+i]q
q-binomial 实践
Codeforces Round #752 (Div. 1)
F. October 18, 2017
先来看一个经典问题,从 n×m 的矩阵中选择一组 n 个线性无关的向量的方案数(0−1 向量)
这个方案数为 i=1∏n(2m−2i−1)
首先来看对于 k 列的子空间,选择非 0 向量的方案数为 2k−1 种,记为 P(k)=2k−1
证明很简单,k 列子空间每一列都可以放 0 或者是 1,这样有 (2k−1) 种不同的非零向量
这些非零向量一定是线性无关的
下面考虑构造向量 ai,假设 ⟨a1,a2,⋯,ai−1⟩ 已经构造好了
ai 要和它们都线性无关,i=4 时如下所示
⎝⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎜⎛⎝⎜⎜⎜⎛10101⋯1001⎠⎟⎟⎟⎞00100⋯1001010101⋯1001⎠⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎟⎞
因为 ⟨a1,a2,⋯,ai−1⟩ 已经构造出来了,它们线性无关
化为行阶梯形矩阵,这些矩阵张成的空间 span(i−1) 秩为 i−1,换句话说
行阶梯形矩阵最高为 1 的位,恰好在列 [0,1,⋯,i−1] 上
于是考虑 ⟨a1,a2,⋯,ai−1⟩ 张成的 i−1 列子空间中,有多少个线性无关向量
答案很显然是 P(i−1)=2i−1−1
那么加入向量 ai,有几种选择方法呢?它肯定不能取 (1P(i−1)) 中任意一种
否则就和 ⟨a1,a2,⋯,ai−1⟩ 相关了,而总的选择数为 2m−1
所以构造 ai 能选择的方案数为 (2m−1)−(2i−1−1)=(2m−2i−1)
根据乘法原理,最后的答案是 i=1∏n(2m−2i−1)
October 18, 2017
题目大意,给出 n,k,x,选一个 n 元组,使得所有数都 <2k,并且满足任意一个子集的异或和不等于 x
算法分析,该问题等价于,将每个数写成二进制形式,n×k 的 01 矩阵中
有多少个秩为 k 的子矩阵,使得这些矩阵张成的向量空间中不包括 x
直观点说,秩为 k 就是化为行阶梯形之后,最高为 1 的位分别在第 [1,2,⋯,k] 位上
注意这里需要特别考虑包不包括 0 向量,一般来说,不包括 0 向量的话
秩为 k 的线性空间中,可以放 2k−1 个线性无关向量
算法设计
(1)
首先,如果 x=0 时等价于秩序为 k 的(即最高的 1 在第 k 位) n 元组线性无关
此时答案就是 i=1∏n(2k−2i−1)
具体的分析见上面
简单来说,第 i−1 个向量可以选择的范围是 (i−1位00⋯0⟶i−1位11⋯1)
用递推的思想,在 i−1 个向量的基础上构造出第 i 个向量,这 (2i−1−1) 个都不能选
否则就线性相关了,所以第 i 个向量方案数为 (2k−1)−(2i−1−1)=2k−2i−1
(2)
假设 x=0,那么此时总的方案数依然是 tot=i=1∏n(2k−2i−1)
只不过需要减掉不符合条件的,也就是说,要减去一个方案数 P
P 由 2 部分构成,第一部分是在 tot 中选出非 0 向量 x,然后考虑将剩下的非线性相关向量构造成基
(2.1)
假设线性空间的维度是 r,考虑 r×k 的线性空间,所有线性无关的方案为 i=1∏r(2k−2i−1)
那么对于 r×k 的线性空间,有 r 个基,如果 x 可以由这些基的一个或者多个线性表出的话,那么肯定不符合条件
r 个基,每个基都可以选或者不选,不能一个也不选,所以构造 x 的方案数为 (2r−1)
那么此时我们得到 ⟨x,a2,a3,⋯,ar⟩
构造 ⟨a2,a3,⋯,ar⟩ 的方案数是 i=2∏r(2k−2i−1)
所以对于 r×k 的线性空间,方案数为
i=1∏r(2k−2i−1)−(2r−1)i=2∏r(2k−2i−1)=i=1∏r(2k−2i−1)(2k−2r)
=i=1∏r(2k−2i)
(2.2)
最后,考虑剩下的 n−r 个向量如何构造?
实际上,经过上面的构造,对于 r×k 的线性空间是满足条件的,接着剩下的 n−r 个向量
考虑由 r×k 的线性空间的基线性表出即可
对于 (n−r) 个向量,考虑将其由前 i 个基表示其中一部分,前 i+1 个基再表示一部分,以此类推
对于前 i 个基,一共可以取 2i 个不同的线性基,(包括 0 向量)
所以可以表示 (n−r) 个向量其中的任意 0,1,2,⋯,n−r 个
也就是说,对于前 i 个基,能构造出来的方案数为
(1+2i+(2i)2+(2i)3+⋯)
所以用前 r 个线性基构造剩下的 n−r 个向量的方案为
i=0∏r(1+2i+(2i)2+⋯)
这里很自然地想到用生成函数,构造 n−r 个向量方案数实际上就是
[xn−r]i=0∏r(1+2ix+(2ix)2+(2ix)3+⋯)=[xn−r]i=0∏r1−2ix1
这个实际上就是 q-binomial 的生成函数
[xn−r]i=0∏r1−2ix1=[rr+n−r]2=[rn]2
(2.3)
那么这部分答案就出来了
r=0∑ni=1∏r(2k−2i)[rn]2
q-binomial 按定义展开即可
[rn]2=[r]!2⋅[n−r]!2[n]!2
其中 [n]!2=[1]!2⋅[2]!2⋅[3]!2⋯[n]!2=i=1∏n1−21−2i=i=1∏n(2i−1)
这些东西全部可以在 O(n) 时间复杂度内预处理完成
实现过程中的细节
首先可以预处理q-binomial的相关项
f(p)=j=1∏p(2p−1) 很容易在 O(n) 时间复杂度内预处理出来
记 inv(p)=2p−11=f(p)1⋅f(p−1)
于是考虑从 p∈(n→1) 递推,更新 f(p)1←f(p−1)1
只要令 x←f(p)1,然后不断令 x←x⋅(2p−1) 即可
考虑如何计算 j=1∏r(2j−1)⋅j=1∏n−r(2j−1)j=1∏n(2j−1)
可以令 Q(r)=j=1∏n−r(2j−1)j=1∏n(2j−1)
这样 r∈(1→n) 遍历的时候,Q(r) 一开始只有 (2n−1) 这一项
由于 n 比较大,此时令 2n=pn,用乘法逆元进行计算
递推的时候,一开始令 Q(r)=(pn−1),然后 Q(r) 每一次要除掉一个 2r−11
这一项已经预处理出来了,就是 Q(r)←Q(r)⋅inv(r),更新 Q(r)←Q(r)⋅(2k−2r)
此时 r 这一项对应的值已经求完了,将 ans+=Q(r)
接着更新 pn=pn/2 (用 2 的逆元计算),然后令 Q(r)←Q(r)⋅(pn−1)
就可以递推到 r←r+1 的情况进行计算了
最后注意,r=0 的情况还没有统计,实际上 r=0 时方案数就是 1
ans+=1 即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| const int maxn = 1e7 + 10; const int N = 1e7;
mint inv[maxn], fac[maxn], infac[maxn]; mint pw[maxn], f[maxn];
void get_pw2() { pw[0] = 1; for (int i = 1; i <= N; i++) pw[i] = pw[i-1] * mint(2); }
void pre() { fac[0] = mint(1); for (int i = 1; i <= N; i++) fac[i] = fac[i-1] * mint(pw[i].x - 1);
mint Q = fac[N].inv(); for (int i = N; i >= 1; i--) { inv[i] = Q * fac[i-1]; Q *= (pw[i] - 1); } }
int solve1(int n, int k) { if (k == 0 or n > k) return 0; mint ans = mint(1); for (int i = 0; i < n; i++) ans = ans * (pw[k] - pw[i]); return ans.x; }
void solve2(int n, int k) { mint inv2 = mint(2).inv();
mint ans = 0; mint Q = mint(1);
mint pn = power(mint(2), n); for (int r = 0; r < k; r++) { ans += Q;
Q *= inv[r+1] * (pn - 1); Q *= (pw[k] - pw[r+1]); pn *= inv2; }
printf("%d\n", ans.x); }
int main() { freopen("input.txt", "r", stdin); get_pw2(); pre();
int cas; cin >> cas; while (cas--) { int n, k, x; scanf("%d%d%d", &n, &k, &x);
if (x == 0) { int ans = solve1(n, k); printf("%d\n", ans); } else { solve2(n, k); } } }
|