[AGC031B] Reversi

[AGC031B] Reversi

题面翻译

\(N\) 块石头摆成一行,从左数第 \(i\) 块石头的颜色是 \(C_i\)

现在すぬけ会进行 \(0\) 次或若干次如下操作:选取两块颜色相同的石头并将两块石头之间的所有石头都染成与这两块石头相同的颜色。

求最终所有可能的石头排列方案数,答案对 \(10^9 + 7\) 取模。

思路

考虑 DP。

考虑第 \(i\) 个石头,如果第 \(i\) 个石头不修改,方案数仍为 \(dp_{i-1}\);如果第 \(i\) 个石头修改,那么贡献就是第 \(i\) 个石头与前面所有颜色相同石头进行操作的可能操作数。

\(\operatorname{pre}_i\) 为上一个与 \(i\) 颜色相同石头的位置。

所以转移方程为

\[dp_i=dp_{i-1}+dp_{\operatorname{pre}_i} \]

Code

#include <bits/stdc++.h>

using namespace std;

const int N = 5005000;
const int Mod = 1e9 + 7;

int n;

int a[N];

int cnt,col[N];

int dp[N],last[N];

int main() {
    ios::sync_with_stdio(false);
    cin >> n;

    for(int i = 1;i <= n; i++) {
        cin >> a[i];
    }
    
    for(int i = 1;i <= n; i++) {
        if(a[i] != a[i - 1]) {
            cnt ++;
            col[cnt] = a[i];
        }
    }

    dp[0] = 1;
    for(int i = 1;i <= cnt; i++) {
        dp[i] = dp[i - 1];

        if(last[col[i]]) {
            int j = last[col[i]];
            dp[i] = (dp[i] + dp[j]) % Mod;
        }

        last[col[i]] = i;
    }

    cout << (dp[cnt] + Mod) % Mod << "\n";
    return 0;
}
posted @ 2023-08-20 15:05  -白简-  阅读(19)  评论(3编辑  收藏  举报