CF1237F Balanced Domino Placements(dp+组合计数)
CF1237F Balanced Domino Placements
- problem
- solution
- code
problem
題目鏈接
solution
骨牌橫著放會占用一行兩列,骨牌豎著放會占用兩行一列。
問題可以抽象為:每次可以選擇連續的兩行放 AAA,或選一行放 BBB;每次可以選一列放 BBB ,或選連續的兩列放 AAA。
且最后行的 AAA 數量等于列的 BBB 數量,列的 AAA 數量等于行的 BBB 數量。【多米諾骨牌大小的匹配】
這樣一個放物品的過程會對應原來很多個多米諾骨牌擺放的方案,因為行列之間 A,BA,BA,B 配對的方案不只一種,任意一種配對方案對應一種不同的擺放方案。
行列之間的 A,BA,BA,B 的擺放是不影響的,只有數量相等的要求。
假設選了 xxx 個 AAA,yyy 個 BBB,則方案數為 x!y!x!y!x!y!。
由于行列互不影響,所以分開求解,最后利用乘法原理計算即可。下面以行為例。
設 dpi,j,k:dp_{i,j,k}:dpi,j,k?: 考慮前 iii 行,放了 jjj 個 AAA,kkk 個 BBB 的方案數。
暴力的狀態都是 n3n^3n3 的,考慮優化。
實際上,BBB 的性質是只占用一行,只要知道剩下的空位,我們就能計算 BBB 的方案數。
改寫 dpi,j:dp_{i,j}:dpi,j?: 前 iii 行放了 jjj 個 AAA ,還沒有放 BBB 的方案數。
那么最后可以放 BBB 的空位為 cnt?2?jcnt-2*jcnt?2?j,cnt:cnt:cnt: 去除掉題目所給多米諾骨牌占用的行后剩下的行數,如果要選 kkk 個 BBB,則可以 O(1)O(1)O(1) 計算方案數為:(cnt?2?jk)\binom{cnt-2*j}{k}(kcnt?2?j?)
最后合并需要枚舉行選了多少個 AAA 和多少個 BBB,枚舉總時間也是 O(n2)O(n^2)O(n2) 的。
所以本題最終的時間復雜度為:O(n2)O(n^2)O(n2)。
code
#include <cstdio> #define int long long #define mod 998244353 #define maxn 3605 int n, m, k, cnt_c, cnt_r; int fac[maxn]; bool row[maxn], col[maxn]; int c[maxn][maxn], f[maxn][maxn], g[maxn][maxn];signed main() {scanf( "%lld %lld %lld", &n, &m, &k );cnt_r = n, cnt_c = m;for( int i = 1, X1, Y1, X2, Y2;i <= k;i ++ ) {scanf( "%lld %lld %lld %lld", &X1, &Y1, &X2, &Y2 );row[X1] = row[X2] = col[Y1] = col[Y2] = 1;cnt_r --, cnt_c --;if( X1 ^ X2 ) cnt_r --;else cnt_c --;}fac[0] = f[0][0] = g[0][0] = c[0][0] = 1;for( int i = 1;i < maxn;i ++ ) fac[i] = fac[i - 1] * i % mod;for( int i = 1;i < maxn;i ++ ) {c[i][0] = c[i][i] = 1;for( int j = 1;j < i;j ++ )c[i][j] = ( c[i - 1][j] + c[i - 1][j - 1] ) % mod;}for( int i = 1;i <= n;i ++ )for( int j = 0;j <= i / 2;j ++ ) {f[i][j] = f[i - 1][j];if( i >= 2 and j and ! row[i] and ! row[i - 1] ) f[i][j] = ( f[i][j] + f[i - 2][j - 1] ) % mod;}for( int i = 1;i <= m;i ++ )for( int j = 0;j <= i / 2;j ++ ) {g[i][j] = g[i - 1][j];if( i >= 2 and j and ! col[i] and ! col[i - 1] ) g[i][j] = ( g[i][j] + g[i - 2][j - 1] ) % mod;}int ans = 0;for( int i = 0;i <= cnt_r / 2;i ++ )for( int j = 0;j <= cnt_c / 2;j ++ )if( i * 2 + j <= cnt_r and i + j * 2 <= cnt_c )ans = ( ans + f[n][i] * g[m][j] % mod * c[cnt_r - 2 * i][j] % mod * c[cnt_c - 2 * j][i] % mod * fac[i] % mod * fac[j] ) % mod;printf( "%lld\n", ans );return 0; } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的CF1237F Balanced Domino Placements(dp+组合计数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CF1368G Shifting Dom
- 下一篇: Excel实现员工工资的排序筛选Exce