Codeforces1142D
Codeforces1142D
做法:構建一個可以識別出合法串的自動機,然后就可以想辦法在上邊 dp 出答案。 首先,按照最直觀的思路畫一畫這個自動機,找到每一個狀態s如何推出它的后繼t,然后通過狀態的轉移方式,找到等價的狀態,想辦法壓縮這個自動機。我們令x的位數是d,ax是比x小的合法的數的數目,bx是位數是d的合法數中比x小的數的數目,cx是位數是d的合法數的數目。那么如果在x后添加一個數字s構成一個數字y,\(ay = ax - bx + cx + cal(ax-bx+1,bx) + s\), \(cal(a,b)\)是從a開始到b在%11下循環求和。 這個式子的\(ax-bx+cx\)就是在計算x的這種位數中最后一個數字的編號,\(cal(ax-bx+1,bx) + s\)就是當前層比y小的數的個數,那么有\(by = cal(ax-bx+1,bx) + s\),\(cy = cal(ax-bx+1,cx)\)。觀察這個轉移的式子,如果 ax+11 會導致 ay + 11,by, cy,如果 bx+11 會導致 ay - 11 + 55, by + 55, cy 如果cx + 11 會導致 ay + 11, by,cy + 55。觀察可以知道 (ax,bx,cx) 在 %11 意義下等價,后繼的數量種類也一致,轉移是有等價性的,于是對于這個三元組(ax,bx,cx)我們建出11 * 11 * 11的狀態轉移圖,而一個子串如果可以在這個圖上完成匹配,他就是合法的。顯然,對于個位置i如果它的最長匹配距離是A,那么答案加A,設\(dp[i][j]\)表示以字符串的第i個位置為起點,自動機的節點j為起點,最長的匹配長度。就有\(dp[i][j] = dp[i+1][nxt(j,s[i+1])] + 1\),其中 \(nxt(s,c)\) 指狀態s后添加一個字符c走到的新狀態,需要注意的一點是,對于任意一種串的位置i和狀態s,dp[i][s]至少為1!!復雜度\(O(11^3 N)\)求解過程中需要理性取模。注意常數
#include <bits/stdc++.h> #define rep(i,a,b) for(int i = (a); i <= (b); ++i) #define per(i,a,b) for(int i = (a); i >= (b); --i) #define pb push_back #define Pll pair<ll,ll> #define Pii pair<int,int> #define Plp pair< ll,Pii > #define Pip pair< int,Pii > #define Ppp pair< Pii,Pii > #define x first #define y second typedef long long ll; const int N = 100100;using namespace std; int cal(int a, int n) {return (( (a+a+n-1)*n/2 )%11+11)%11; } int n, dp[2][11][11][11]; char s[N]; ll ans;int main() {scanf(" %s",s+1); n = strlen(s+1);int f = 0;per(i, n, 1) {int now = s[i] - '0', nx = s[i+1] - '0';rep(a, 0, 10) rep(b, 0, 10) rep(c, 0, 10) {dp[f][a][b][c] = 1;if(i == n) continue;if( (a+1)%11 <= nx ) continue;int ta = (a - b + 11 + c + cal(a-b+1,b) + nx) % 11;int tb = (cal(a-b+1,b) + nx) %11 ;int tc = cal(a-b+1,c);dp[f][a][b][c] = dp[f^1][ta][tb][tc] + 1;}if(now) ans += dp[f][now-1][now-1][9];f ^= 1;}printf("%lld\n",ans);return 0; }轉載于:https://www.cnblogs.com/RRRR-wys/p/10668310.html
總結
以上是生活随笔為你收集整理的Codeforces1142D的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cid是什么意思 cid有多重含义吗
- 下一篇: 反向传播算法学习笔记