矩阵(递推)

标题挺短啊,有点不适应。

题面

有一个 n × n \tt n\times n n×n 01 \tt01 01 矩阵,当它每一行、每一列都恰好有两个位置是 1 \tt1 1 的时候,称为配对矩阵。

请问从 1 × 1 \tt1\times1 1×1 n × n \tt n\times n n×n 的所有 01 \tt01 01 矩阵中有多少矩阵为配对矩阵。

f ( i ) \tt f(i) f(i) 表示 i × i \tt i\times i i×i 的配对矩阵的个数,即询问:
∑ i = 1 n f ( i ) \tt\sum_{i=1}^{n} f(i) i=1nf(i)

答案对 998244353 \tt998244353 998244353 取模, 1 ≤ n ≤ 1 e 7 \tt1\leq n\leq1e7 1n1e7.

题解

如果,我们把矩阵第 i i i 行第 j j j 列的元素为 1 ,看作是:在第 i i i 行和第 j j j 列之间连一条边,那么,就是这么一个二分图:两边各有 n n n 个点,每个行的结点的度数是 2,列的结点的度数也是 2,整张图形成若干个四元以上的环,每个环一半的点是行结点。

我们不妨从行结点的角度考虑问题。若我们钦定一共 k k k 个环,每个环的结点数为 a 1 , a 2 , a 3 , . . . , a k   ( ∑ a i = n ) a_1,a_2,a_3,...,a_k~(\sum a_i=n) a1,a2,a3,...,ak (ai=n) ,那么把 n n n 个行结点放入这些环中,初步方案数为 n ! ∏ ( a i ! ) \frac{n!}{\prod (a_i!)} (ai!)n! ,再在环内部进行排列,进一步的方案数为
n ! ∏ ( a i ! ) ⋅ ∏ ( a i ! ) = n ! \frac{n!}{\prod (a_i!)}\cdot \prod (a_i!)=n! (ai!)n!(ai!)=n!

(赞美太阳) 这时候把列结点塞进去、塞进每个环内行结点之间的空隙里,方案数变为
n ! ⋅ n ! = ( n ! ) 2 n!\cdot n!=(n!)^2 n!n!=(n!)2

考虑旋转同构和翻转同构,再考虑到环与环之间是无序的,除去标号影响,方案数最终为
( n ! ) 2 k ! ⋅ ∏ 2 a i \frac{(n!)^2}{k!\cdot\prod 2a_i} k!2ai(n!)2

也就是说
f ( 0 ) = 1   ,   f ( n ) = ∑ k , a ( n ! ) 2 k ! ⋅ ∏ 2 a i (1) f(0)=1~,~f(n)=\sum_{k,a}\frac{(n!)^2}{k!\cdot\prod 2a_i}\tag{1} f(0)=1 , f(n)=k,ak!2ai(n!)2(1)


好,现在的问题是要枚举 a a a 序列。每个 f ( i ) f(i) f(i) 都枚举整个序列是不现实的,我们可以考虑从前面的状态转移过来。

注意到一点,我们在一个方案中挖去一个环后,把剩下的点按顺序重新标号,它又是一个完整的方案,只不过 n n n 要变小。

那么我们不妨就枚举第一行代表的结点所在的环,把这个环挖去后的状态,当然就是一种前驱状态了。主要枚举该环的大小(环中行结点的个数),然后把环排列、列结点、翻转重构等再次考虑进去:
f ( i ) = ∑ j = 2 i f ( i − j ) ⋅ ( i − 1 ) ! ( i − j ) ! ⋅ i ! ( i − j ) ! ⋅ 1 2 f(i)=\sum_{j=2}^{i}f(i-j)\cdot\frac{(i-1)!}{(i-j)!}\cdot\frac{i!}{(i-j)!}\cdot \frac{1}{2} f(i)=j=2if(ij)(ij)!(i1)!(ij)!i!21

我们把两边同除一个 ( i ! ) 2 (i!)^2 (i!)2 ,会惊奇地发现:
f ( i ) ( i ! ) 2 = ∑ j = 2 i f ( i − j ) ( ( i − 1 ) ! ) 2 ⋅ 1 2 i \frac{f(i)}{(i!)^2}=\sum_{j=2}^{i}\frac{f(i-j)}{((i-1)!)^2}\cdot\frac{1}{2i} (i!)2f(i)=j=2i((i1)!)2f(ij)2i1

或许不那么惊奇,但是我们可以令 d p ( i ) = f ( i ) ( i ! ) 2 dp(i)=\cfrac{f(i)}{(i!)^2} dp(i)=(i!)2f(i) ,再转变枚举顺序试试:
d p ( i ) = ( ∑ j = 0 i − 2 d p ( j ) ) ⋅ 1 2 i (2) dp(i)=\bigg(\sum_{j=0}^{i-2}dp(j)\bigg)\cdot\frac{1}{2i}\tag{2} dp(i)=(j=0i2dp(j))2i1(2)

顿时变得可做了! ( 2 ) (2) (2) 式明显可以一边计算一边处理前缀和,然后就达到 O ( n ) O(n) O(n)

那么,为什么前面还要推 ( 1 ) (1) (1) 式呢?……

练练手呗, 前面的 ( 1 ) (1) (1) 式给了我们推导 ( 2 ) (2) (2) 式的思路,不然的话,后面的推理会变得没来由。

CODE

如果不往生成函数方面想的话,并不难。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 10000005
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
LL read() {
	LL f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
	while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
	return f * x;
}
const int MOD = 998244353;
int n,m,i,j,s,o,k;
int inv[MAXN];
int as[MAXN];
int main() {
	freopen("matrix.in","r",stdin); // or "rune.in" ?
	freopen("matrix.out","w",stdout);
//	F[i]/(i!)^2 = \sum_{j=1}^{i-1} F[i-j-1]/((i-j-1)!)^2 * 1/2
//  DP[i] = (\sum_{j=1}^{i-1} DP[i-j-1]) * 1/2i
	n = read();
	inv[0] = inv[1] = 1;
	for(int i = 2;i <= n;i ++) {
		inv[i] = (MOD-inv[MOD%i]) *1ll* (MOD/i) % MOD;
	}
	as[0] = 1;
	int sm = 0,ans = 0,fac = 1;
	for(int i = 2;i <= n;i ++) {
		fac = fac *1ll* i % MOD;
		(sm += as[i-2]) %= MOD;
		as[i] = sm *1ll* inv[i] % MOD *1ll* inv[2] % MOD;
		(ans += as[i]*1ll*fac%MOD *1ll*fac%MOD) %= MOD;
	}
	printf("%d\n",ans);
	return 0;
}

殊途同归

曾经有化学老师说过,不管剂量谈毒害就是耍流氓。同样的,不管实力大小,怎能谈难度?

这不, T L Y \tt TLY TLY 太阳神 不就用生成函数做出来了?


神谕:

可以令 A ( x ) = ∑ k > 1 a k ( k ! ) 2 x k = ∑ k > 1 k ! × ( k − 1 ) ! × 1 / 2 ( k ! ) 2 x k = ( ln ⁡ ( 1 1 − x ) − x ) / 2 A(x)=\sum_{k>1}\frac{a_k}{(k!)^2}x^k=\sum_{k>1}\frac{k!\times(k-1)!\times1/2}{(k!)^2}x^k=(\ln(\frac{1}{1-x})-x)/2 A(x)=k>1(k!)2akxk=k>1(k!)2k!×(k1)!×1/2xk=(ln(1x1)x)/2,那么关于答案 F ( x ) = ∑ k > 1 f k ( k ! ) 2 x k F(x)=\sum_{k>1}\frac{f_k}{(k!)^2}x^k F(x)=k>1(k!)2fkxk F ( x ) = exp ⁡ A ( x ) F(x)=\exp A(x) F(x)=expA(x),直接代入可得 F ( x ) = e − x / 2 1 − x F(x)=\frac{e^{-x/2}}{\sqrt{1-x}} F(x)=1x ex/2

由于数据范围,而 F ( x ) F(x) F(x) 又是微分有限的(它是两个微分有限形式幂级数的乘积),尝试对其微分得 F ′ ( x ) = e − x / 2 x 2 ( 1 − x ) 3 / 2 = x 2 ( 1 − x ) F ( x ) F'(x)=\frac{e^{-x/2}x}{2(1-x)^{3/2}}=\frac{x}{2(1-x)}F(x) F(x)=2(1x)3/2ex/2x=2(1x)xF(x),于是得到 f n = 1 2 n ∑ i = 0 n − 2 f i f_n=\frac{1}{2n}\sum_{i=0}^{n-2} f_i fn=2n1i=0n2fi

硬要说的话,也可以做。


T L Y \tt TLY TLY 太阳神 无所不能!

posted @ 2021-07-19 20:23  DD_XYX  阅读(79)  评论(0编辑  收藏  举报