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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

AtCoder3950 [AGC022E] Median Replace(DFA + dp)

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

problem

solution

可以從 DFA\text{DFA}DFA 的思想來考慮這道題。

考慮建一個 DFA\text{DFA}DFA 只接受最后可以變成字符串 111 的原串。

因為每次是選擇三個 連續/相鄰 的位置操作,限制是比較強的,無非有三種情況。

  • case1 三個全 111,操作后只剩 111111,相當于刪去兩個 111
  • case2 三個全 000,操作后只剩 111000,相當于刪去兩個 000
  • case3 剩下的組合,操作后只剩 1110/10/10/1,但都相當于刪去 010101 各一個。

顯然貪心地我們是不會操作 case1 減少 111 的數量的。而連續的 000 的數量也不會超過 222 個,超過一定可以操作回來。

只有 111 的數量大于等于 000 的數量就是合法的。

事實上最后情況 111 的數量絕對不可能跟 000 數量相同,因為題目保證輸入串是奇數長度,而每次的操作都減少兩個長度。

111 多了反正都會被接受,沒必要在 DFA\text{DFA}DFA 上建立這么多狀態。

我們將所有 111 的個數超過兩個的狀態都連回個數為 222 的狀態,然后接受這個狀態即可。

所以 DFA\text{DFA}DFA 的狀態數是 1(0/1/2)?0(0/1/2)=3?3=91(0/1/2)-0(0/1/2)=3·3=91(0/1/2)?0(0/1/2)=3?3=9 種的。

最后就是在這個 DFA\text{DFA}DFA 上跑 dpdpdp 即可。

f(i,j,k):f(i,j,k):f(i,j,k): 到字符串的第 iii 位,此時狀態為 jjj111kkk000 的方案數。考慮向 i+1i+1i+1 位轉移。

  • si+1=0s_{i+1}=0si+1?=0,直接增加 000 個個數即可。
    • k=2k=2k=2,case2 操作。f(i,j,2)→f(i+1,j,0)f(i,j,2)\rightarrow f(i+1,j,0)f(i,j,2)f(i+1,j,0)
    • k≠2k\neq 2k?=2f(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)
  • si+1=1s_{i+1}=1si+1?=1。在這個時候才考慮跟 000 的抵消情況。
    • k=0k=0k=0f(i,j,0)→f(i+1,min?(j+1,2),0)f(i,j,0)\rightarrow f(i+1,\min(j+1,2),0)f(i,j,0)f(i+1,min(j+1,2),0)
    • k≠0k\neq 0k?=0,case3 操作,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)
  • si+1=?s_{i+1}=?si+1?=?,將上面兩種情況都跑一遍即可。

code

#include <bits/stdc++.h> using namespace std; #define mod 1000000007 #define int long long #define maxn 300005 char s[maxn]; int n, ans; int f[maxn][3][3];signed main() {scanf( "%s", s + 1 );n = strlen( s + 1 );f[0][0][0] = 1;//f[i][j][k]:到字符串第i位時 有j個1 k個0for( int i = 0;i < n;i ++ ) {if( s[i + 1] != '0' ) {for( int j = 0;j <= 2;j ++ ) {( f[i + 1][j][0] += f[i][j][1] ) %= mod;( f[i + 1][j][1] += f[i][j][2] ) %= mod;( f[i + 1][min( j + 1, 2ll )][0] += f[i][j][0] ) %= mod;}}if( s[i + 1] != '1' ) {for( int j = 0;j <= 2;j ++ ) {( f[i + 1][j][1] += f[i][j][2] ) %= mod;( f[i + 1][j][2] += f[i][j][1] ) %= mod;( f[i + 1][j][1] += f[i][j][0] ) %= mod;}}}for( int i = 0;i <= 2;i ++ )for( int j = 0;j <= i;j ++ )( ans += f[n][i][j] ) %= mod; printf( "%lld\n", ans );return 0; }

總結

以上是生活随笔為你收集整理的AtCoder3950 [AGC022E] Median Replace(DFA + dp)的全部內容,希望文章能夠幫你解決所遇到的問題。

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