自动机
https://www.cnblogs.com/do-while-true/p/16759278.html
DFA
一个确定有限状态自动机(DFA)的组成:
- 非空有限的字符集 \(Σ\);
- 非空有限的状态集合 \(Q\);
- 开始状态 \(start∈Q\);
- 接受状态的集合 \(F⊆Q\);
- 转移函数 \(δ=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;
}