LibreOJ 6502 「雅礼集训 2018 Day4」Divide 题解 [ 蓝 ] [ 多维 DP ] [ 构造 ]
神仙题。
一个显然的想法是我们把人按照某种顺序排序,之后根据有序的性质进行 DP。但是你发现本题中“有序”这个性质根本用不上,我们需要找到另一种性质构造排列使其能够直接 DP。
注意到把人按照 \(w_i\) 排序后,若最后一个人和第一个人的和 \(\bm{w_n+w_1\ge m}\),那么对于 $\bm{\forall 1 \le i< n} $,都有 \(\bm{w_n + w_i\ge m}\)。这是个非常好进行 DP 的性质,即保证每个人都能与其前面的所有人决斗。但是我们发现有些人并不能满足这个性质。又发现当 \(w_n+w_1< m\) 的时候,对于 $\forall 1 < i\le n $,都有 \(w_1+w_i<m\)。这同样是一个非常好的性质,即保证每个人都不能与其前面的所有人决斗。发现这两个限制拼在一起就能构成全集,所以对原序列这样递归构造下去,我们就一定能得到目标排列。
于是定义 \(dp_{i, j}\) 表示前 \(i\) 个人中,有 \(j\) 个在 A 队的最大匹配与方案数,转移即可。时间复杂度 \(O(n^2)\)。
#include <bits/stdc++.h>
#define fi first
#define se second
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
#define lc(x) (tr[x].ls)
#define rc(x) (tr[x].rs)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi = pair<int, int>;
using pl = pair<int, ll>;
const int N = 2005, inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
int n, m, a[N], p[N], cnt;
void divide(int l, int r)
{
if(l == r)
{
p[cnt--] = a[l];
return;
}
if(a[l] + a[r] >= m)
{
p[cnt--] = a[r];
divide(l, r - 1);
return;
}
p[cnt--] = a[l];
divide(l + 1, r);
}
pl dp[N][N];
void add(pl &x, pl y)
{
if(x.fi < y.fi)
{
x = y;
return;
}
else if(x.fi == y.fi)
{
x.se += y.se;
if(x.se >= mod) x.se -= mod;
}
}
int main()
{
//freopen("sample.in", "r", stdin);
//freopen("sample.out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1);
cnt = n;
divide(1, n);
for(int i = 0; i <= n; i++)
for(int j = 0; j <= n; j++)
dp[i][j] = {-inf, 0};
dp[1][0] = dp[1][1] = {0, 1};
for(int i = 2; i <= n; i++)
{
for(int j = 0; j <= i; j++)
{
if(p[i] + p[1] >= m)
{
if(j - 1 >= 0)
{
pl res = dp[i - 1][j - 1];
res.fi += i - 1 - (j - 1);
add(dp[i][j], res);
}
pl res = dp[i - 1][j];
res.fi += j;
add(dp[i][j], res);
}
else
{
if(j - 1 >= 0) add(dp[i][j], dp[i - 1][j - 1]);
add(dp[i][j], dp[i - 1][j]);
}
}
}
pl ans = {-1, 0};
for(int i = 0; i <= n; i++)
add(ans, dp[n][i]);
cout << ans.fi << " " << ans.se;
return 0;
}

浙公网安备 33010602011771号