P9418 题解
题意回顾
给定一个长度为
分析
当一个数字出现三次及以上或出现两次且两次位置差不为
在把出现两次的位置确定好后,我们考虑把每个仅出现一次的
定义
最后我们要把空位置填上所有未在
时间复杂度
AC 代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e5 + 5;
const int mod = 1e9 + 7;
int n;
int a[N];
int buc[N];
int typ[N], dne[N];
int dp[N][2][2];
int main() {
scanf("%d", &n);
bool ok = true;
int o = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
if(buc[a[i]] == 0) buc[a[i]] = i;
else if(buc[a[i]] > 0) {
if(buc[a[i]] != i - 2) ok = false;
buc[a[i]] = -1;
o++, dne[i - 1] = 1, typ[i - 2] = typ[i] = 1;
} else ok = false;
}
if(!ok) {
puts("0");
return 0;
}
//for(int i = 1; i <= n; i++) cout << dne[i] << typ[i] << endl;
dp[1][0][1] = 1;
for(int i = 2; i <= n; i++) {
if(typ[i]) {
dp[i][1][dne[i + 1]] = (dp[i - 1][0][1] + dp[i - 1][1][1]) % mod;
if(!dne[i]) dp[i][0][dne[i + 1]] = (dp[i - 1][0][0] + dp[i - 1][1][0]) % mod;
} else {
if(!dne[i]) dp[i][0][0] = dp[i - 1][0][0], dp[i][0][1] = (dp[i - 1][1][0] + dp[i - 1][0][0]) % mod,
dp[i][1][0] = dp[i - 1][0][1], dp[i][1][1] = (dp[i - 1][1][1] + dp[i - 1][0][1]) % mod;
else dp[i][1][0] = dp[i - 1][0][1], dp[i][1][1] = (dp[i - 1][0][1] + dp[i - 1][1][1]) % mod;
}
//cout << i << " " << dp[i][0][0] << " " << dp[i][0][1] << " " << dp[i][1][0] << " " << dp[i][1][1] << endl;
}
int ans = (dp[n][1][0] + dp[n][0][0]) % mod;
for(int i = 1; i <= o; i++) ans = (long long)ans * i % mod;
printf("%d\n", ans);
return 0;
}