rank
solved
A
B
C
D
E
F
G
H
I
J
K
11/64
6/11
O
.
O
O
.
O
O
!
O
.
!
A 夺宝奇兵 Solved by Henry.
C 最小边覆盖 Solved by wb and Henry.
D 欧拉回路 Solved by Henry.
F 小小马 Solved by Henry and wb.
G 置置置换 Solved by XLor.
求所有 $1$ 到 $n$ 的排列,满足一下的条件的方案数,对于所有的 $i$$(2 \le i \le n)$,若 $i$ 为奇数,则 $a[i-1]<a[i]$,否则 $a[i-1]>a[i]$。
考虑 $dp[i][j]$ 表示 $1$ 到 $i$ 的排列,最后一个数为 $j$ 的方案数。
不妨令 $i$ 为偶数,那么 $dp[i][j]$ 对应了 $1,2,\dots,j-1,j+1,\dots,i-1$ ,这 $i-1$ 个数可以建立一个映射到 $1,2,\dots ,i-1$,那么
$$ dp[i][j] = dp[i-1][j]+dp[i-1][j+1]+ \dots +dp[i-1][i-1] $$
$i$ 为奇数时为前缀和。
时间复杂度为 $O(n^2)$。
H 命命命运 Unsolved by Henry and wb.
I 咆咆咆哮 Solved by Henry.
给出 $n$ 张牌,每张牌有两种属性 $a_i$ 和 $b_i$,你可以选择一种属性出牌,出 $a_i$ 表示召唤一个场攻为 $a_i$ 的随从,出 $b_i$ 表示每个随从攻击力加 $b_i$,现在要求最大化场攻。
显然,必须先召唤随从,然后使用咆哮。可以注意到场攻是关于随从数量的一个凸函数(不会证明),因此考虑三分。
$check$ 函数计算召唤 $x$ 个随从时的最大场攻,可以先当作所有牌都是召唤出随从,然后对 $x b_i-a_i$ 排序,选出最大的 $n-x$ 张牌,作为咆哮使用。
K 两条路径 Unsolved by XLor.
权值线段树维护二进制位。
简单版:权值为 $2$ 的幂次,求最短路,The Classic Problem 。
代码 G 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 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define ms(a,b) memset(a,b,sizeof(a)) using namespace std;typedef long long ll;const int mod = 1e9 + 7 ;const int maxn = 1000 + 5 ;int n, dp[maxn][maxn], pre[maxn][maxn], suf[maxn][maxn];int main () { scanf ("%d" , &n); dp[1 ][1 ] = 1 ; dp[2 ][1 ] = 1 ; dp[2 ][2 ] = 0 ; pre[1 ][1 ] = 1 ; pre[2 ][1 ] = 1 ; pre[2 ][2 ] = 1 ; pre[2 ][3 ] = 1 ; suf[1 ][1 ] = 1 ; suf[2 ][0 ] = 1 ; suf[2 ][1 ] = 1 ; suf[2 ][2 ] = 0 ; for (int i = 3 ; i <= n; i++) { if (i % 2 ) { for (int j = i; j >= 1 ; j--) { dp[i][j] = pre[i - 1 ][j - 1 ]; suf[i][j] = (suf[i][j + 1 ] + dp[i][j]) % mod; } suf[i][0 ] = suf[i][1 ]; } else { for (int j = 1 ; j <= i; j++) { dp[i][j] = suf[i - 1 ][j]; pre[i][j] = (pre[i][j - 1 ] + dp[i][j]) % mod; } pre[i][i + 1 ] = pre[i][i]; } } int ans = 0 ; for (int i = 1 ; i <= n; i++) ans = (ans + dp[n][i]) % mod; cout << ans << endl; return 0 ; }
I 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 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <utility> #define ms(a,b) memset(a,b,sizeof(a)) using namespace std;typedef long long ll;typedef pair<int , int > PII;const int mod = 1e9 + 7 ;const int maxn = 100000 + 5 ;int n, k;PII a[maxn]; ll sum; bool cmp (PII a, PII b) { ll x = 1ll * k * a.second - a.first, y = 1ll * k * b.second - b.first; return x > y; } ll cal (int x) { k = x; nth_element (a, a + n - x, a + n, cmp); ll s = 0 ; for (int i = 0 ; i < n - x; i++) s += 1ll * k * a[i].second - a[i].first; return s + sum; } int main () { scanf ("%d" , &n); for (int i = 0 ; i < n; i++) scanf ("%d%d" , &a[i].first, &a[i].second), sum += a[i].first; int l = 0 , r = n; while (l + 2 < r) { int ml = (2 * l + r) / 3 , mr = (l + 2 * r) / 3 ; ll s1 = cal (ml), s2 = cal (mr); if (s1 < s2) l = ml; else r = mr; } cout << max (max (cal (l), cal (r)), max (cal ((2 * r + l) / 3 ), cal ((2 * l + r) / 3 ))) << endl; return 0 ; }