求環的一道dp題ios
對於本題來講,對於每個造成的新環,都有兩種狀態中的一種狀態轉移而來spa
設定f[i][j]表明i我的造成j個環的方案數code
狀態一:由f[i-1][j]轉移過來,對於每個位置都有插空的可能性,因此須要×(n-1)blog
狀態二:由f[i-3][j-1]轉移過來,咱們能夠獲得在兩個環組成一個新的環的時候,能夠由i-3我的圍成j-1個環,而後再選出兩我的去拉手組成一個大環io
由於由i-1個的小環插入的時候須要×(i-1),而後對於i-3我的的時候插入就須要在這個基礎上在×(i-2) //這是顯然的,由於這個組合是隨機的,順序均爲單向class
#include<iostream> #include<cstdio> #define MAXN 2003 #define ll long long using namespace std; ll n,k,p; ll dp[MAXN << 1][MAXN]; int main() { scanf("%lld%lld%lld",&n,&k,&p); dp[0][0] = 1; for(ll i=1;i<=n;i++) for(ll j=1;j<=min(i / 3,k);j++) dp[i][j] = (dp[i - 1][j] * (i - 1) % p + dp[i - 3][j - 1] * (i - 1) * (i - 2) % p) % p; printf("%lld",dp[n][k]); return 0; }