牛客网多校训练第一场 B - Symmetric Matrix(dp)
鏈接:
https://www.nowcoder.com/acm/contest/139/B
?
題意:
求滿足以下條件的n*n矩陣A的數量模m:
A(i,j) ∈ {0,1,2}, 1≤i,j≤n.
A(i,j) = A(j,i), 1≤i,j≤n.
A(i,1) + A(i,2) + ... + A(i,n) = 2, 1≤i≤n.
A(1,1) = A(2,2) = ... = A(n,n) = 0.
其中1≤n≤1e5, 1≤m≤1e9。
?
分析:
把矩陣看成無向圖的鄰接矩陣,即要求所有點度為2,即每個點都屬于一個環。
設d(n)表示n個點滿足條件的圖的數量。
思考每加入一個新點,如何從已知狀態轉移。
1.從前面的n-1個點中選出1個點與新點構成環,有(n-1)d(n-2)種方案。
2.從前面的n-1個點中選出k個點,剩下的點與新點連成環,
有sum(C(n-1,k)*(n-1-k)!/2)(2≤k≤n-3)種方案,
因為剩下的點與新點連成環時的對稱性,所以要除以2。
將以上兩式化簡相加,得d(n) = (n-1)d(n-2) + sum((n-1)!d(k)/k!/2)(2≤k≤n-3)。
設f(n) = sum((n-1)!d(k)/k!/2)(2≤k≤n-3)。
可以發現,f(n)也是可以遞推的,即f(n) = (n-1)f(n-1) + (n-1)(n-2)d(n-3)/2。
所以,線性時間遞推f和d數組即可。
?
代碼:
1 import java.io.*; 2 import java.util.*; 3 4 public class Main { 5 Scanner cin = new Scanner(new BufferedInputStream(System.in)); 6 final int UP = (int)1e5 + 5; 7 long d[] = new long[UP], f[] = new long[UP]; 8 9 void MAIN() { 10 while(cin.hasNext()) { 11 int n = cin.nextInt(); 12 long m = cin.nextInt(); 13 14 d[2] = d[3] = f[3] = 1 % m; 15 for(int i = 4; i <= n; i++) { 16 f[i] = ((i-1) * f[i-1] % m + (long)(i-1) * (i-2) / 2 % m * d[i-3] % m) % m; 17 d[i] = ((i-1) * d[i-2] % m + f[i]) % m; 18 } 19 System.out.println(d[n]); 20 } 21 } 22 23 public static void main(String args[]) { new Main().MAIN(); } 24 }
?
轉載于:https://www.cnblogs.com/hkxy125/p/9356303.html
總結
以上是生活随笔為你收集整理的牛客网多校训练第一场 B - Symmetric Matrix(dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: qq个性签名一句话短语
- 下一篇: pip install lxml失败原因