链接:
题意:
两个人玩游戏,第一个人首先选择一棵
n
个点且度数不超过
翻转 a[i+1⋯k] ,并让这一段整体加上 ai 。
将 a[i+1⋯k] 取负,并让这一段整体加上 ai 。
最后如果
a
是严格单调的则第一个人胜,问两个人都使用最优策略时有多少种不同的
题解:
题意有毒…
第一个人会选择让自己必胜的树,什么序列能让自己必胜呢?有两种:单调的或者单峰的 ,对于这种序列有两种 (i,op) ,自己画一画就懂了。
所以这种树任意一条路径都是单调或者单峰的。
记第一个人必胜的树的个数为 |T| ,则 ans=2n(n−1)|T| 。
记
f(i,j)
表示
i
个节点,根的度数为
用前缀和可以优化到 O(n3) 。
最后将父亲编号小于儿子编号树的个数和大于的并起来就是答案,但是一棵树可能有多个合法的根,会算重。
注意到有多个合法的根时根一定满足是一条编号连续的链,要求另外一边根的度数不能为 1 <script type="math/tex" id="MathJax-Element-1524">1</script>就不会算重了。
代码:
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 205;
uint ans, mod, c[N][N], f[N][N], s[N][N];
int n, m;
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(m), Read(mod);
for (int i = 0; i <= n; ++i) {
c[i][0] = 1;
for (int j = 1; j <= i; ++j) {
c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
}
}
f[1][0] = 1;
for (int i = 0; i <= m; ++i) {
s[1][i] = 1;
}
for (int i = 2; i <= n; ++i) {
for (int j = 1; j < i; ++j) {
for (int k = 0; k < m; ++k) {
f[i][k + 1] = (1LL * s[j][m - 1] * c[i - 2][j - 1] % mod * f[i - j][k] + f[i][k + 1]) % mod;
}
}
for (int j = 1; j <= m; ++j) {
s[i][j] = (s[i][j - 1] + f[i][j]) % mod;
}
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j <= m; ++j) {
for (int k = 0; j + k <= m; ++k) {
if (k != 1) {
ans = (1LL * f[i + 1][j] * f[n - i][k] + ans) % mod;
}
}
}
}
ans = 2LL * n * (n - 1) * ans % mod;
printf("%u\n", ans);
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}