乍一看並不好發現遞推式,我們需要巧妙的轉化。
我們將每乙個1
11視作是行列之間的連邊,於是我們發現每乙個方案對應的是若干個環的劃分。
所以我們考慮對這個矩陣的若干個點進行劃分。
考慮列舉列舉第一行所在的環的狀態(即行和列),令a
ia_i
ai表示i×i
i\times i
i×i的矩陣中只有乙個環的狀態數,則我們有如下遞推式:
f n=
∑i=2
n(ni
)(n−
1i−1
)aif
n−
if_n=\sum_^a_if_
fn=i=
2∑n
(in
)(i−
1n−1
)ai
fn−
i列舉有多少個行與第一行在同一環中,這i
ii個環佔了哪些列,刪去這i
ii行i
ii列之後,剩下的就是乙個(n−
i)×(
n−i)
(n-i)\times (n-i)
(n−i)×
(n−i
)的矩陣,就可以得到上面的式子。
現在考慮這個東西:a
ia_i
ai怎麼求。
考慮將原來的矩陣行列分別化為點,那麼最後的連成的就是乙個兩邊各有n
nn個點的單環二分圖。
首先匹配一波,對於左邊的每個點選擇右邊尚未匹配的點,這一步的方案數就是n!n!
n!。然後進行第二次匹配,我們找到左1
11號點的右匹配點,在左邊任意選擇乙個尚未進行二次匹配且不是1
11號的點進行第二次匹配,對匹配到的點的第一次匹配點,我們重複上面的過程。注意,由於要求是乙個單環,所以不能在最後乙個點之前匹配左1
11號點。這一部分的方案數就是(n−
1)
!(n-1)!
(n−1)!
我們發現這個過程的逆過程也被計算了一次,所以需要除以222。
但是這個式子仍然不能方便的維護字首和,考慮進一步轉化。
將原式的組合數拆成階乘:
f n=
∑i=2
nn!i
!(n−
i)!⋅
(n−1
)!(i
−1)!
(n−i
)!i!
(i−1
)!2f
n−
if_n=\sum_^\frac\cdot\frac\fracf_
fn=i=
2∑n
i!(n
−i)!
n!⋅
(i−1
)!(n
−i)!
(n−1
)!2
i!(i
−1)!
fn−
i化簡得到:
f n=
n!(n
−1)!
2∑i=
2nfn
−i((
n−i)
!)
2f_n=\frac\sum_^n\frac}
fn=2n
!(n−
1)!
i=2∑
n((
n−i)
!)2f
n−i
發現兩邊似乎有長得很像的結構:
f n(
n!)2
=12n
∑i=2
nfn−
i((n
−i)!
)2
\frac=\frac\sum_^\frac}
(n!)2f
n=
2n1
i=2∑
n((
n−i)
!)2f
n−i
設g n=
fn(n
!)
2g_n=\frac
gn=(n
!)2f
n就可以愉快的轉移了。
逆元線性推一下就行了。
**:
#include
#define ll long long
#define re register
#define cs const
cs int mod=
998244353
;inline
intadd
(int a,
int b)
inline
intdec
(int a,
int b)
inline
intmul
(int a,
int b)
cs int n=
1e7+7;
int inv[n]
,inv2;
int n,g,gsum,glast,ans,fac;
signed
main()
std::cout<"\n"
;return0;
}
組合數學 求組合數
對於求組合數,要根據所給資料範圍來選擇合適的演算法 這道題中所給的資料範圍適合用打表的方法直接暴力求解 先用4e6的複雜度預處理出所有的情況,再用1e4的複雜度完成詢問即可 include using namespace std const int n 2010 const int mod 1e9 ...
bzoj1008 越獄 組合數學
監獄有連續編號為1 n的n個房間,每個房間關押乙個犯人,有m種宗教,每個犯人可能信仰其中一種。如果相鄰房間的犯人的宗教相同,就可能發生越獄,求有多少種狀態可能發生越獄 輸入兩個整數m,n.1 m 10 8,1 n 10 12 可能越獄的狀態數,模100003取餘 2 366種狀態為 000 001 ...
BZOJ 1008 越獄(組合數學)
思路 首先全部情況有m n種,不滿足題意的情況有m m 1 n 1 種情況,然後快速冪就好啦 include includeusing namespace std define ll long long define mod 100003 ll powmod ll a,ll b return ans...