NC17134 Symmetric Matrix
Problem Statement
数有多少个 n × n n\times n n×n的矩阵满足下列条件:
- A i , j ∈ { 0 , 1 , 2 } , 1 ≤ i , j ≤ n A_{i,j}\in\{0,1,2\},1\leq i,j\leq n Ai,j∈{0,1,2},1≤i,j≤n.
- A i , j = A j , i , 1 ≤ i , j ≤ n A_{i,j}=A_{j,i},1\leq i,j\leq n Ai,j=Aj,i,1≤i,j≤n.
- ∑ i = 1 n A j , i = 2 , j ∈ [ 1 , n ] \sum_{i=1}^nA_{j,i}=2,j\in[1,n] ∑i=1nAj,i=2,j∈[1,n].
- A i , i = 0 , i ∈ [ 1 , n ] A_{i,i}=0,i\in[1,n] Ai,i=0,i∈[1,n].
Solution
由于性质 2 2 2可知, A A A是一个对称矩阵. 因此我们可以把 A A A看作为一个 n n n个点的无向图的邻接矩阵.
那问题就转化成, 有 n n n个点, 每个点的度数都是 2 2 2, 且不存在自环, 但是允许有重边(重边当且仅当在二元环中出现).
那么我们考虑递推/第二类数学归纳法,
设 f k f_k fk表示 k k k个点满足上述要求的方案数.
k ≤ n − 1 k\leq n-1 k≤n−1的 f k f_k fk已经求出了. 现在我们通过 f k , k ≤ n − 1 f_k,k\leq n-1 fk,k≤n−1去求 f n f_n fn.
现在添加了一个点, 它需要和之前存在的一个点形成环.
如果添加的一个点和之前的点形成了一个二元环的方案数是 ( n − 1 ) f n − 2 (n-1)f_{n-2} (n−1)fn−2.
如果添加的一个点和之前的点形成了一个 k k k元环, 得方案数 ∑ k = 0 n − 3 ( C n − 1 k × f k × ( n − k − 1 ) ! 2 ) \sum_{k=0}^{n-3}(C_{n-1}^k\times f_k\times\frac{(n-k-1)!}{2}) ∑k=0n−3(Cn−1k×fk×2(n−k−1)!).
-
f n = ( n − 1 ) f n − 2 + ∑ k = 0 n − 3 ( n − 1 ) ! 2 × k ! f k f_n=(n-1)f_{n-2}+\sum_{k=0}^{n-3}\frac{(n-1)!}{2\times k!}f_k fn=(n−1)fn−2+∑k=0n−32×k!(n−1)!fk.
-
f n − 1 = ( n − 2 ) f n − 3 + ∑ k = 0 n − 4 ( n − 2 ) ! 2 × k ! f k f_{n-1}=(n-2)f_{n-3}+\sum_{k=0}^{n-4}\frac{(n-2)!}{2\times k!}f_k fn−1=(n−2)fn−3+∑k=0n−42×k!(n−2)!fk.
f n − ( n − 1 ) f n − 1 = ( n − 1 ) f n − 2 + ∑ k = 0 n − 3 ( n − 1 ) ! 2 × k ! f k − ( n − 1 ) ( n − 2 ) f n − 3 − ∑ k = 0 n − 4 ( n − 1 ) ! 2 × k ! f k f_n-(n-1)f_{n-1}=(n-1)f_{n-2}+\sum_{k=0}^{n-3}\frac{(n-1)!}{2\times k!}f_k-(n-1)(n-2)f_{n-3}-\sum_{k=0}^{n-4}\frac{(n-1)!}{2\times k!}f_k fn−(n−1)fn−1=(n−1)fn−2+∑k=0n−32×k!(n−1)!fk−(n−1)(n−2)fn−3−∑k=0n−42×k!(n−1)!fk.
化简可得 f n = ( n − 1 ) ( f n − 1 + f n − 2 ) − ( n − 1 ) ( n − 2 ) 2 f n − 3 f_n=(n-1)(f_{n-1}+f_{n-2})-\frac{(n-1)(n-2)}{2}f_{n-3} fn=(n−1)(fn−1+fn−2)−2(n−1)(n−2)fn−3.
边界: f 1 = 0 , f 2 = f 3 = 1 f_1=0,f_2=f_3=1 f1=0,f2=f3=1.
算法复杂度为 O ( n ) O(n) O(n).
Code
# define Fast_IO std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
# include "unordered_map"
# include "algorithm"
# include "iostream"
# include "cstdlib"
# include "cstring"
# include "cstdio"
# include "vector"
# include "bitset"
# include "queue"
# include "cmath"
# include "map"
# include "set"
using namespace std;
const int maxm=1e5+10;
int N,Mod;
long long DP[maxm];
int main(){
static long long i;
while(~scanf("%d%d",&N,&Mod)){
DP[1]=0,DP[2]=DP[3]=1;
for(i=4;i<=N;i++){
DP[i]=((i-1)*(DP[i-1]+DP[i-2])-(i-1)*(i-2)/2*DP[i-3]%Mod+Mod)%Mod;
}printf("%lld\n",(DP[N]+Mod)%Mod);
}
return 0;
}
Link
Link 1: NC17134 Symmetric Matrix