自动机

https://www.cnblogs.com/do-while-true/p/16759278.html

DFA

一个确定有限状态自动机(DFA)的组成:

  1. 非空有限的字符集 \(Σ\)
  2. 非空有限的状态集合 \(Q\)
  3. 开始状态 \(start∈Q\)
  4. 接受状态的集合 \(F⊆Q\)
  5. 转移函数 \(δ=Q×Σ→Q\)

也就是说,一个 DFA 由这样一个五元组组成,它可以一个字符一个字符地输入一个字符串,从 \(start\) 开始,每次根据转移函数转移到下一个状态,如果最终停在终止状态,则称该自动机接受此字符串。

DFA 很像一个有向图,在 OI 中将其视作一个有向图即可。

一个应用是,将 dp 转移写成 DFA 的形式,然后压缩这个 DFA,然后在这个 DFA 上跑矩阵快速幂来优化转移。

CF1766E Descomposition

【题意】

For a sequence of integers $ [x_1, x_2, \dots, x_k] $ , let's define its decomposition as follows:

Process the sequence from the first element to the last one, maintaining the list of its subsequences. When you process the element $ x_i $ , append it to the end of the first subsequence in the list such that the bitwise AND of its last element and $ x_i $ is greater than $ 0 $ . If there is no such subsequence in the list, create a new subsequence with only one element $ x_i $ and append it to the end of the list of subsequences.

For example, let's analyze the decomposition of the sequence $ [1, 3, 2, 0, 1, 3, 2, 1] $ :

  • processing element $ 1 $ , the list of subsequences is empty. There is no subsequence to append $ 1 $ to, so we create a new subsequence $ [1] $ ;
  • processing element $ 3 $ , the list of subsequences is $ [[1]] $ . Since the bitwise AND of $ 3 $ and $ 1 $ is $ 1 $ , the element is appended to the first subsequence;
  • processing element $ 2 $ , the list of subsequences is $ [[1, 3]] $ . Since the bitwise AND of $ 2 $ and $ 3 $ is $ 2 $ , the element is appended to the first subsequence;
  • processing element $ 0 $ , the list of subsequences is $ [[1, 3, 2]] $ . There is no subsequence to append $ 0 $ to, so we create a new subsequence $ [0] $ ;
  • processing element $ 1 $ , the list of subsequences is $ [[1, 3, 2], [0]] $ . There is no subsequence to append $ 1 $ to, so we create a new subsequence $ [1] $ ;
  • processing element $ 3 $ , the list of subsequences is $ [[1, 3, 2], [0], [1]] $ . Since the bitwise AND of $ 3 $ and $ 2 $ is $ 2 $ , the element is appended to the first subsequence;
  • processing element $ 2 $ , the list of subsequences is $ [[1, 3, 2, 3], [0], [1]] $ . Since the bitwise AND of $ 2 $ and $ 3 $ is $ 2 $ , the element is appended to the first subsequence;
  • processing element $ 1 $ , the list of subsequences is $ [[1, 3, 2, 3, 2], [0], [1]] $ . The element $ 1 $ cannot be appended to any of the first two subsequences, but can be appended to the third one.

The resulting list of subsequences is $ [[1, 3, 2, 3, 2], [0], [1, 1]] $ .

Let $ f([x_1, x_2, \dots, x_k]) $ be the number of subsequences the sequence $ [x_1, x_2, \dots, x_k] $ is decomposed into.

Now, for the problem itself.

You are given a sequence $ [a_1, a_2, \dots, a_n] $ , where each element is an integer from $ 0 $ to $ 3 $ . Let $ a[i..j] $ be the sequence $ [a_i, a_{i+1}, \dots, a_j] $ . You have to calculate $ \sum \limits_{i=1}^n \sum \limits_{j=i}^n f(a[i..j]) $ .
$ 1 \le n \le 3 \cdot 10^5, 0 \le a_i \le 3 $.

【分析】
考虑 \(dp_{i, 0/1/2/3, 0/1, 0/1}\) 表示以 \(i\) 为结尾的串里面,第一堆顶是 \(0/1/2/3\),有/没有额外的 \(1\) 堆,有/没有额外的 \(2\) 堆的方案数。其中 \(0\) 的贡献单独处理。转移按照题意来即可。也可以看作一个 DFA。(两者并无明确区分)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define f(i, a, b) for(int i = (a); i <= (b); i++)
#define cl(i, n) i.clear(),i.resize(n);
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 1e9;
void cmax(int &x, int y) {if(x < y) x = y;}
void cmin(int &x, int y) {if(x > y) x = y;}
int au[2][13];
int a[300010];
int calc(int x) {
    int ret = 0;
    ret += (au[x][1] + au[x][2] + au[x][3]) * 1;
    ret += (au[x][4] + au[x][5] + au[x][6] + au[x][10] + au[x][11] + au[x][12]) * 2;
    ret += (au[x][7] + au[x][8] + au[x][9]) * 3;
    return ret;
}
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(NULL);
    cout.tie(NULL);
    //time_t start = clock();
    //think twice,code once.
    //think once,debug forever.
    int ans = 0;
    int n; cin >> n;
    f(i, 1, n) cin >> a[i];
    f(i, 1, n) {
        if(a[i] == 0) ans += (i * (n - i + 1));
    }
    f(i, 1, n) {
        f(j, 0, 12) au[i & 1][j] = 0;
        if(a[i] == 0) {
            f(j, 0, 12) au[i & 1][j] = au[(i & 1) ^ 1][j];
            au[i & 1][0] ++;
        }
        else if(a[i] == 1) {
            au[i & 1][1] += au[(i & 1) ^ 1][0];
            au[i & 1][1] += au[(i & 1) ^ 1][1];
            au[i & 1][5] += au[(i & 1) ^ 1][2];
            au[i & 1][1] += au[(i & 1) ^ 1][3];
            au[i & 1][4] += au[(i & 1) ^ 1][4];
            au[i & 1][5] += au[(i & 1) ^ 1][5];
            au[i & 1][4] += au[(i & 1) ^ 1][6];
            au[i & 1][7] += au[(i & 1) ^ 1][7];
            au[i & 1][8] += au[(i & 1) ^ 1][8];
            au[i & 1][7] += au[(i & 1) ^ 1][9];
            au[i & 1][10] += au[(i & 1) ^ 1][10];
            au[i & 1][8] += au[(i & 1) ^ 1][11];
            au[i & 1][10] += au[(i & 1) ^ 1][12];
            au[i & 1][1] ++;  
        }
        else if(a[i] == 2) { 
            au[i & 1][2] += au[(i & 1) ^ 1][0];
            au[i & 1][10] += au[(i & 1) ^ 1][1];
            au[i & 1][2] += au[(i & 1) ^ 1][2];
            au[i & 1][2] += au[(i & 1) ^ 1][3];
            au[i & 1][7] += au[(i & 1) ^ 1][4];
            au[i & 1][5] += au[(i & 1) ^ 1][5];
            au[i & 1][5] += au[(i & 1) ^ 1][6];
            au[i & 1][7] += au[(i & 1) ^ 1][7];
            au[i & 1][8] += au[(i & 1) ^ 1][8];
            au[i & 1][8] += au[(i & 1) ^ 1][9];
            au[i & 1][10] += au[(i & 1) ^ 1][10];
            au[i & 1][11] += au[(i & 1) ^ 1][11];
            au[i & 1][11] += au[(i & 1) ^ 1][12];
            au[i & 1][2] ++;                      
        }
        else if(a[i] == 3) {   
            au[i & 1][3] += au[(i & 1) ^ 1][0];
            au[i & 1][3] += au[(i & 1) ^ 1][1];
            au[i & 1][3] += au[(i & 1) ^ 1][2];
            au[i & 1][3] += au[(i & 1) ^ 1][3];
            au[i & 1][6] += au[(i & 1) ^ 1][4];
            au[i & 1][6] += au[(i & 1) ^ 1][5];
            au[i & 1][6] += au[(i & 1) ^ 1][6];
            au[i & 1][9] += au[(i & 1) ^ 1][7];
            au[i & 1][9] += au[(i & 1) ^ 1][8];
            au[i & 1][9] += au[(i & 1) ^ 1][9];
            au[i & 1][12] += au[(i & 1) ^ 1][10];
            au[i & 1][12] += au[(i & 1) ^ 1][11];
            au[i & 1][12] += au[(i & 1) ^ 1][12];
            au[i & 1][3] ++;              
        }
        ans += calc(i & 1);
    }
    cout << ans << endl;
    //time_t finish = clock();
    //cout << "time used:" << (finish-start) * 1.0 / CLOCKS_PER_SEC <<"s"<< endl;
    return 0;
}
posted @ 2022-12-15 15:12  OIer某罗  阅读(24)  评论(0编辑  收藏  举报