AGC031B Reversi

$dp$ 计数.

设 $f(i)$ 表示前 $i$ 个位置的方案数.

转移时,若能找到上一个与 $i$ 颜色相同的位置 $j$ ,并且 $i,j$ 中间还有数,那么将这段染色是有贡献的.

注意此时应当加上 $f(j)$ 而不是 $f(j-1)$ ,因为 $i,j$ 同色,将 $j\sim i$ 这段染色不会影响以 $j$ 为右端点向前面染色.
$$
f(i)=f(i-1)+f(j)\cdot [i-j>1]
$$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//%std
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read()
{
int out=0,fh=1;
char jp=getchar();
while ((jp>'9'||jp<'0')&&jp!='-')
jp=getchar();
if (jp=='-')
fh=-1,jp=getchar();
while (jp>='0'&&jp<='9')
out=out*10+jp-'0',jp=getchar();
return out*fh;
}
const int P=1e9+7;
int add(int a,int b)
{
return (a+b>=P)?(a+b-P):(a+b);
}
int mul(int a,int b)
{
return 1LL * a * b % P;
}
const int MAXN=2e5+10;
int n,f[MAXN],lst[MAXN];
int main()
{
n=read();
f[0]=1;
for(int i=1;i<=n;++i)
{
f[i]=f[i-1];
int c=read();
if(lst[c] && i-lst[c]>1)
f[i]=add(f[i],f[lst[c]]);
lst[c]=i;
}
cout<<f[n]<<endl;
return 0;
}