Chess Championship

题目描述

Chess Championship is set up in the New Basyuki City. Two national teams, of Berland and Byteland, are going to have a match there. Each team is represented by $n$ players. The championship consists of $n$ games - in each game a pair of players from different teams meets. A game victory brings $1$ point to the team and a game defeat doesn’t add or subtract points.

The championship starts with the sortition - the process that determines opponent pairs. Each player from the first team plays with exactly one player from the second team (and vice versa).

A recent research conducted by Berland scientists showed that every player of either team is characterized by a single number - the level of his chess mastership. No two people among the $2n$ players play at the same level. Funny as it is, the game winner always is the player with the higher level.

The contest organizers received information that a high-ranking Berland official Mr. B. bet $100500$ burles on the victory of his team with a $k$ points gap. Immediately an unofficial “recommendation” came from very important people to “organize” the sortition so that the Berland team gets exactly $k$ points more than the Byteland team.

Write a program that finds the number of distinct sortition results after which Berland gets exactly $k$ points more than Byteland. Two sortitions are considered distinct if there is such player, that gets different opponents by the sortitions’ results.

题意概述

给定两组数$a_i, b_i$,每组$n$个数。保证所有$a_i, b_i$中不会出现相同的数。求有多少个排列$p$满足$\sum_{i=1}^n [a_i \gt b_{p_i}]-\sum_{i=1}^n [a_i \lt b_{p_i}]=k$。

数据范围:$1 \le k \le n \le 500$。

算法分析

当$k \not \equiv n \pmod 2$时,排列不存在。

将所有数从小到大排序。令$f_{i, j, k}$表示在前$i$个数中,有$j$个$a$中的数匹配了$b$中比它小的数,有$k$个$b$中的数匹配了$a$中比它小的数的方案数。转移时只要计算前$i$个数中两组分别有几个数未匹配,枚举第$i$个数是否匹配另一组中比它小的数。最后的答案就是$f_{2n, {n+k \over 2}, {n-k \over 2}}$。

需要滚动数组。

代码

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
#include <algorithm>
#include <cstdio>
#include <cstring>

static int const N = 505;
static int const MOD = 1000000009;
int f[2][N][N];
std::pair<int, int> a[N << 1];

int main() {
int n, k;
scanf("%d%d", &n, &k);
if ((n & 1) != (k & 1))
return puts("0"), 0;
for (int i = 0; i < n; ++i)
scanf("%d", &a[i].first);
for (int i = n; i < n << 1; ++i)
scanf("%d", &a[i].first), a[i].second = 1;
std::sort(a, a + (n << 1));
int cur = 0, s[2] = {0, 0};
f[0][0][0] = 1;
for (int i = 0; i < n << 1; ++i, cur ^= 1) {
for (int j = 0; j <= n; ++j)
for (int k = 0; j + k <= n; ++k)
if (f[cur][j][k]) {
(f[!cur][j][k] += f[cur][j][k]) %= MOD;
int c[2] = {s[0] - j - k, s[1] - j - k};
(f[!cur][j + !a[i].second][k + a[i].second] += 1ll * f[cur][j][k] * c[!a[i].second] % MOD) %= MOD;
f[cur][j][k] = 0;
}
++s[a[i].second];
}
printf("%d\n", f[cur][n + k >> 1][n - k >> 1]);
return 0;
}

Chess Championship
https://regmsif.cf/2018/04/30/oi/chess-championship/
作者
RegMs If
发布于
2018年4月30日
许可协议