[牛客139B-Symmetric Matrix]

这篇博客探讨了如何计算满足特定条件的N×N矩阵的数量,其中矩阵元素的限制和节点度数的约束转化为图论问题。通过建立递推公式,解析了矩阵对称性的计算过程,并提供了相关代码实现。
摘要由CSDN通过智能技术生成

题意:

给定 N N N, 求有多少个大小为 N × N N \times N N×N 的矩阵 A A A,满足
A i i = 0 , ∀ i ∈ [ 1 , N ] 0 ≤ A i j = A j i ≤ 2 , ∀ i , j ∈ [ 1 , N ] , i ≠ j ∑ j = 1 N A i j = 2 , ∀ i ∈ [ 1 , N ] A_{ii} = 0, \quad \forall i \in [1, N] \\ 0 \le A_{ij} = A_{ji} \le 2, \quad \forall i, j \in [1, N], i \ne j\\ \sum_{j = 1}^{N} A_{ij} = 2, \quad \forall i \in [1, N]\\ Aii=0,i[1,N]0Aij=Aji2,i,j[1,N],i̸=jj=1NAij=2,i[1,N]

分析:

将矩阵视为 N N N 个点的图邻接矩阵,则题意转化为有多少种图满足节点度数都为2。可以有重边,但是不可以有自环。

计算过程:

f ( n ) f(n) f(n) n n n 个点时应输出的结果。考虑在节点数为 n − 1 n-1 n1 个图上加一个点。如果点 n n n 构成了重边,则必只与 { 1 , 2 , … , n − 1 } \{1, 2, \dots, n-1\} {1,2,,n1} 中一个点相连,剩余 n − 2 n-2 n2 个点自己解决自己的问题,所以有 ( n − 1 ) f ( n − 2 ) (n-1) f(n-2) (n1)f(n2) 种情况。
如果没有构成重边,则点 n n n 连通的点数一定超过 2 2 2 个,所以从 n − 1 n-1 n1 个里选 k   (   2 ≤ k ≤ n − 1 ) k\ (\ 2\le k\le n-1) k ( 2kn1) 个点与 n n n 相连,有 C n − 1 k C_{n-1}^{k} Cn1k 种。剩余 n − 1 − k n-1-k n1k 个点自己解决自己,有 f ( n − 1 − k ) f(n-1-k) f(n1k) 种,其中与 k k k 个点相连通时,考虑从环的断点加入新点, k k k 个点的链有 k ! k! k! 种情况,围起来情况数少一半,因为这个链正着排和倒着排围起来是一样的。有 k ! 2 \frac{k!}{2} 2k! 种。所以一共有 ∑ 2 ≤ k &lt; n − 2 C n − 1 k k ! 2 f ( n − 1 − k ) = ∑ 2 ≤ k &lt; n − 2 ( n − 1 ) ! k ! ( n − 1 − k ) ! k ! 2 f ( n − 1 − k ) \displaystyle\sum_{2\le k\lt n-2} C_{n-1}^k \frac{k!}{2} f(n-1-k) = \displaystyle\sum_{2\le k\lt n-2} \frac{(n-1)!}{k!(n-1-k)!} \frac{k!}{2} f(n-1-k) 2k<n2Cn1k2k!f(n1k)=2k<n2k!(n1k)!(n1)!2k!f(n1k) ( n − 1 ) ! ∑ 2 ≤ k &lt; n − 2 f ( n − 1 − k ) 2 ( n − 1 − k ) ! \displaystyle(n-1)!\sum_{2\le k\lt n-2} \frac{f(n-1-k)}{2(n-1-k)!} (n1)!2k<n22(n1k)!f(n1k) 种。则 f ( n ) = ( n − 1 ) f ( n − 2 ) + ( n − 1 ) ! ∑ 2 ≤ k &lt; n − 2 f ( n − 1 − k ) 2 ( n − 1 − k ) ! f(n) = (n-1)f(n-2) + \displaystyle(n-1)!\sum_{2\le k\lt n-2} \frac{f(n-1-k)}{2(n-1-k)!} f(n)=(n1)f(n2)+(n1)!2k<n22(n1k)!f(n1k) g ( n ) = ( n − 1 ) ! ∑ 2 ≤ k &lt; n − 2 f ( n − 1 − k ) 2 ( n − 1 − k ) ! g(n) = \displaystyle(n-1)!\sum_{2\le k\lt n-2} \frac{f(n-1-k)}{2(n-1-k)!} g(n)=(n1)!2k<n22(n1k)!f(n1k) 得到
g ( n − 1 ) = ( n − 2 ) ! ∑ 2 ≤ p ≤ n − 4 f ( p ) 2 p ! g(n-1) = (n-2)! \displaystyle\sum_{2\le p\le n-4} \frac{f(p)}{2p!} g(n1)=(n2)!2pn42p!f(p)
g ( n ) = ( n − 1 ) ! ∑ 2 ≤ p ≤ n − 3 f ( p ) 2 p ! g(n) = (n-1)! \displaystyle\sum_{2\le p\le n-3} \frac{f(p)}{2p!} g(n)=(n1)!2pn32p!f(p)所以可以凑齐 f ( ) f() f()项后得出比例,即
g ( n ) = ( n − 1 ) [ g ( n − 1 ) + ( n − 2 ) ! f ( n − 3 ) 2 ( n − 3 ) ! ] g(n) = (n-1)[g(n-1) + (n-2)!\frac{f(n-3)}{2(n-3)!}] g(n)=(n1)[g(n1)+(n2)!2(n3)!f(n3)]化简
g ( n ) = ( n − 1 ) g ( n − 1 ) + ( n − 1 ) ( n − 2 ) 2 f ( n − 3 ) g(n) = (n-1)g(n-1) + \frac{(n-1)(n-2)}{2}f(n-3) g(n)=(n1)g(n1)+2(n1)(n2)f(n3)
至此得到了 g ( n ) g(n) g(n) 的线性递推式,同时也得出了 f ( n ) f(n) f(n) 的线性递推公式。所以问题解决。

代码

#include <bits/stdc++.h>

using namespace std;
const int N_MAX = 1e5 + 10;
long long f[N_MAX], g[N_MAX];
long long N, M;

int main() {
  f[2] = f[3] = 1;
  g[3] = 1;
  while (~scanf("%lld%lld", &N, &M)) {
    for (long long i = 4; i <= N; i++) {
      g[i] = (i-1) * g[i-1] % M + ((i-1) * (i-2)/2) % M * f[i-3] % M;
      g[i] %= M;
      f[i] = (i-1) * f[i-2] % M + g[i] % M;
      f[i] %= M;
    }
    printf("%lld\n", f[N]);
  }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值