F.天桥
题目传送门
https://acm.ecnu.edu.cn/contest/340/problem/F/
思路
给你n个块(n为偶数),要对这n个块进行上色,有k种颜色可以选取,上的颜色需要两两配对并且不能交叉。若第x与y同色,u与v同色,当且仅当x<u<y<v时被认为是交叉。
g[i]长度为2i的合法染色序列个数 f[i]长度为2i 该序列的贪心括号序列中最外层括号的颜色不为某个特定色的方案数
因此我们可以得出转移方程
g[i]=(k-1)(sum^{n}_{j=1})g[j]g[i-j-1]
f[i]=k(sum^{n}_{j=1})g[j]f[i-j-1]
代码实现
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
inline ll read(){
ll f=0,num;
char ch;
while(ch=getchar(),!isdigit(ch))if(ch=='-')f=1;num=ch-'0';
while(ch=getchar(), isdigit(ch))num=num*10+ch-'0';
return f?-num:num;
}
const int mod = 1e9 + 7;
const int N = 3e3 + 3;
ll f[N],g[N];
//g[i]长度为2i的合法染色序列个数 f[i]长度为2i 该序列的贪心括号序列中最外层括号的颜色不为某个特定色的方案数
int main(){
int n,k;
n = read();k = read();
g[0] = 1;
for (int i = 1; i <= n / 2; i++) {
for (int j = 0; j <= i - 1; j++) {
g[i] = (g[i] + 1ll * (k - 1) * g[i - j - 1] * g[j] % mod ) % mod;
}
}
f[0] = 1;
for (int i = 1; i <= n / 2; i++) {
for (int j = 0; j <= i - 1; j++) {
f[i] = (f[i] + 1ll * k * g[i - j - 1] * f[j] % mod ) % mod;
}
}
cout<<f[n/2]<<endl;
return 0;
}