日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AtCoder4515 [AGC030F] Permutation and Minimum(dp)

發布時間:2023/12/3 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 AtCoder4515 [AGC030F] Permutation and Minimum(dp) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

problem

洛谷鏈接

solution

一個 AiA_iAi? 只會影響一個 BiB_iBi?BiB_iBi? 之間的決定因素 AAA 是不會有交的。

所以如果相鄰兩個對同一個 BiB_iBi? 影響的 A2i,A2i?1A_{2i},A_{2i-1}A2i?,A2i?1? 都是確定的,那么 BiB_iBi? 也就確定了。

這是不會對方案數產生貢獻的,提前預處理掉這些位置,接下來的計算不考慮這些出現的值。

同時,如果都不確定,這些配對位置的值可以互換,即原本 ?1-1?1 的位置是無序的,所以最后的答案要乘上一個階乘。

BiB_iBi? 是取較小值,容易想到從大到小考慮填的數,那么BiB_iBi? 就僅由 A2i,A2i?1A_{2i},A_{2i-1}A2i?,A2i?1? 后填的數決定。

下面將 A2i?1,A2iA_{2i-1},A_{2i}A2i?1?,A2i? 沒全填的稱為“未配對”。

f(i,j,k):f(i,j,k):f(i,j,k): 已考慮到數第 iii 大時,有 jjj 個明確指定的數還未配對,有 kkk 個原本未知 ?1-1?1 然后填了個數也還未配對 的方案數。

考慮由 f(i,j,k)f(i,j,k)f(i,j,k) 轉移到 i+1i+1i+1,即 Ai+1A_{i+1}Ai+1? 的配對情況。

  • 如果 Ai+1A_{i+1}Ai+1? 原本是指定的數,Ai+1≠?1A_{i+1}\neq -1Ai+1??=?1

    • 可以和未知數配對,f(i,j,k)→f(i+1,j,k?1)f(i,j,k)\rightarrow f(i+1,j,k-1)f(i,j,k)f(i+1,j,k?1)
    • 可以新增一個已知數的未配對,f(i,j,k)→f(i,j+1,k)f(i,j,k)\rightarrow f(i,j+1,k)f(i,j,k)f(i,j+1,k)
  • 如果 Ai+1=?1A_{i+1}=-1Ai+1?=?1,未知。

    • 可以新增一個未知數的未配對,f(i,j,k)→f(i,j,k+1)f(i,j,k)\rightarrow f(i,j,k+1)f(i,j,k)f(i,j,k+1)

    • 可以和未知數配對,f(i,j,k)→f(i+1,j,k?1)f(i,j,k)\rightarrow f(i+1,j,k-1)f(i,j,k)f(i+1,j,k?1)

    • 可以和已知數配對,f(i,j,k)×j→f(i+1,j?1,k)f(i,j,k)\times j\rightarrow f(i+1,j-1,k)f(i,j,k)×jf(i+1,j?1,k)

      因為已知數的位置是固定的,所以 Ai+1A_{i+1}Ai+1?jjj 個已知數配對都是不同的情況。

      而和未知數的配對是不考慮 ×k\times k×k 的。本來位置就不固定,在最后的階乘時候已經算入了,這里再乘就算重了。

初始狀態 f(0,0,0)=1f(0,0,0)=1f(0,0,0)=1

code

#include <bits/stdc++.h> using namespace std; #define mod 1000000007 #define int long long #define maxn 605 int n, m, cnt, fac; int a[maxn], c[maxn], g[maxn]; int f[maxn][maxn][maxn];signed main() {scanf( "%lld", &n ), n <<= 1;for( int i = 1;i <= n;i ++ ) scanf( "%lld", &a[i] );for( int i = 1;i <= n;i += 2 ) {if( a[i] == -1 and a[i + 1] == -1 ) cnt ++;else if( ~ a[i] and ~ a[i + 1] ) g[a[i]] = g[a[i + 1]] = 2;else {if( ~ a[i] ) g[a[i]] = 1;else g[a[i + 1]] = 1;}}for( fac = 1;cnt;fac = fac * cnt % mod, cnt -- );for( int i = n;i;i -- ) if( g[i] ^ 2 ) c[++ m] = i;f[0][0][0] = 1;for( int i = 0;i < m;i ++ )for( int j = 0;j <= n;j ++ )for( int k = 0;k <= n;k ++ )if( ! f[i][j][k] ) continue;else if( g[c[i + 1]] ) { //已知數( f[i + 1][j + 1][k] += f[i][j][k] ) %= mod; //新增一個未匹配的已知數if( k ) ( f[i + 1][j][k - 1] += f[i][j][k] ) %= mod; //和未知數匹配}else { //未知數( f[i + 1][j][k + 1] += f[i][j][k] ) %= mod; //新增一個未匹配的未知數if( j ) ( f[i + 1][j - 1][k] += f[i][j][k] * j % mod ) %= mod; //和已知數配對if( k ) ( f[i + 1][j][k - 1] += f[i][j][k] ) %= mod; //和未知數匹配}printf( "%lld\n", f[m][0][0] * fac % mod );return 0; }

總結

以上是生活随笔為你收集整理的AtCoder4515 [AGC030F] Permutation and Minimum(dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。