【2021夏纪中游记】2021.8.14模拟赛
比赛概括:
\(\mathrm{sum}=26.7+0+40+0\)
T1 [USACO 2021 US Open]Do You Know Your ABCs? S:
题目大意:
思路:
暴力把输入的数按升序填入 \(A,B,C,A+B,A+C,B+C,A+B+C\),因为有的时候 \(C > A+B\),换个位子就行。
代码:
const int N = 10;
inline ll Read()
{
ll x = 0, f = 1;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x * f;
}
int n;
int r[N], ans;
int vis[N];
struct ANS
{
int a, b, c;
ANS(int A, int B, int C) {a = A, b = B, c = C;}
bool operator < (const ANS &A) const
{
return a < A.a || (b < A.b && a == A.a) || (c < A.c && b == A.b && a == A.a);
}
};
map <ANS, int> hash;
bool AeB(int a, int b) {return a == 0 || a == b;}
bool check(int a, int b, int c)
{
return a > 0 && b >= a && c >= b && AeB(vis[1], a) && AeB(vis[2], b) && AeB(vis[3], c) && AeB(vis[4], a + b) && AeB(vis[5], a + c) && AeB(vis[6], b + c) && AeB(vis[7], a + b + c) && !hash[ANS(a, b, c)];
}
int ch[5][4] = {{}, {2, 3}, {1, 0, 3}, {0, 1, 2}};
int a[5];
int TwoSame(int x, int y, int z)
{
a[x] = vis[x], a[y] = vis[y];
bool flag = 1;
if (vis[z]) a[z] = vis[z], flag = 0;
else
for (int i = 4; i <= 6; i++)
{
if (i == 7 - z || !vis[i]) continue;
a[z] = vis[i] - vis[ch[z][i-4]];
flag = 0; break;
}
if (flag)
a[z] = vis[7] - vis[x] - vis[y];
if (check(a[1], a[2], a[3])) hash[ANS(a[1], a[2], a[3])] = 1, ans++;
}
int OneSame(int x, int y, int z)
{
a[x] = vis[x];
for (int i = 4; i <= 6; i++)
{
if (i == 7 - x || !vis[i]) continue;
a[ch[x][i-4]] = vis[i] - vis[x];
}
if (vis[7 - x])
if (a[y]) a[z] = vis[7 - x] - a[y];
else a[y] = vis[7 - x] - a[z];
if (check(a[1], a[2], a[3])) hash[ANS(a[1], a[2], a[3])] = 1, ans++;
}
void Check()
{
a[1] = a[2] = a[3] = 0;
if (vis[1] && vis[2]) {TwoSame(1, 2, 3); return;}
if (vis[1] && vis[3]) {TwoSame(1, 3, 2); return;}
if (vis[3] && vis[2]) {TwoSame(2, 3, 1); return;}
if (vis[1]) {OneSame(1, 2, 3); return;}
if (vis[2]) {OneSame(2, 1, 3); return;}
if (vis[3]) {OneSame(3, 1, 2); return;}
int v7 = (vis[4] + vis[5] + vis[6]) / 2;
a[1] = v7 - vis[6];
a[2] = v7 - vis[5];
a[3] = v7 - vis[4];
if (check(a[1], a[2], a[3])) hash[ANS(a[1], a[2], a[3])] = 1, ans++;
}
void dfs(int x, int k)
{
if (x == 8 && k != n + 1) return;
if (k == n + 1)
{
Check();
vis[3] ^= vis[4] ^= vis[3] ^= vis[4];
Check();
vis[3] ^= vis[4] ^= vis[3] ^= vis[4];
return ;
}
dfs(x + 1, k);
vis[x] = r[k];
dfs(x + 1, k + 1);
vis[x] = 0;
}
int main()
{
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
for (int t = Read(); t--; )
{
memset (vis, 0, sizeof vis);
hash.clear();
ans = 0;
n = Read();
for (int i = 1; i <= n; i++)
r[i] = Read();
sort (r + 1, r + 1 + n);
dfs(1, 1);
printf ("%d\n", ans);
}
return 0;
}
T2 [USACO 2021 US Open, Silver]Acowdemia:
题目大意:
思路:
二分 \(h\) 指数。
代码:
const int N = 1e5 + 10;
inline ll Read()
{
ll x = 0, f = 1;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x * f;
}
ll n, k, L;
int a[N];
bool check(int x)
{
ll cnt = 0;
for (int i = n - x + 1; i <= n; i++)
{
if (x <= a[i]) break;
if (x - a[i] > k) return 0;
cnt += x - a[i];
}
return cnt <= k * L;
}
int main()
{
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
n = Read(), k = Read(), L = Read();
for (int i = 1; i <= n; i++) a[i] = Read();
sort (a + 1, a + 1 + n);
int l = 1, r = n, ans = 0;
while (l <= r)
{
int mid = l + r >> 1;
if (check(mid)) l = mid + 1, ans = mid;
else r = mid - 1;
}
printf ("%d\n", ans);
return 0;
}
T3 [USACO 2021 US Open, Gold]United Cows of Farmer John:
题目大意:
枚举点 \(i\) 左右最远能到达的值 \(l_i,r_i\)。那么如果 \([L,R]\) 要合法,就有 \(L+1\leq R\leq r_L,l_R\leq L\)。典型二维偏序。
代码:
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ZYC using
#define AK namespace
#define IOI std
#define ll long long
ZYC AK IOI;
const int N = 2e5 + 10;
inline ll Read()
{
ll x = 0, f = 1;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x * f;
}
int n;
int a[N], lst[N], L[N], R[N];
ll ans;
int t[N];
void modify(int x, int val) {for (; x <= n; x += x & -x) t[x] += val;}
int query(int x)
{
int ans = 0;
for (; x; x -= x & -x) ans += t[x];
return ans;
}
vector <int> Dame[N];
int main()
{
n = Read();
for (int i = 1; i <= n; lst[a[i]] = i, i++)
a[i] = Read(), L[i] = lst[a[i]] + 1;
memset (lst, 0, sizeof lst);
for (int i = 1; i <= n; i++) lst[i] = n + 1;
for (int i = n; i; lst[a[i]] = i, i--)
R[i] = lst[a[i]] - 1;
for (int i = 1; i <= n; i++)
modify(i, 1), Dame[L[i]].push_back(i);
for (int l = n - 1; l; l--)
{
for (int i = 0; i < Dame[l + 1].size(); i++)
modify(Dame[l + 1][i], -1);
ans += query(R[l]) - query(l); //[l+1,R[l]]
}
printf ("%lld", ans);
return 0;
}
T4 [USACO 2021 US Open, Silver]Maze Tac Toe:
题目大意:
思路:
暴力搜索。
代码:
const int N = 30, M = 5, K = 20010;
inline ll Read()
{
ll x = 0, f = 1;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x * f;
}
int n;
int A[M][M], win[K], pw[K];
bool vis[N][N][K], Vis[K];
char a[N][N * 3];
bool Win(int S)
{
for (int i = 1; i <= 3; i++)
for (int j = 1; j <= 3; j++)
{
A[i][j] = S % 3;
S /= 3;
}
for (int i = 1; i <= 3; i++)
{
if (A[i][1] == 1 && A[i][2] == 2 && A[i][3] == 2) return 1;
if (A[i][1] == 2 && A[i][2] == 2 && A[i][3] == 1) return 1;
if (A[1][i] == 1 && A[2][i] == 2 && A[3][i] == 2) return 1;
if (A[1][i] == 2 && A[2][i] == 2 && A[3][i] == 1) return 1;
}
if (A[1][1] == 1 && A[2][2] == 2 && A[3][3] == 2) return 1;
if (A[1][1] == 2 && A[2][2] == 2 && A[3][3] == 1) return 1;
if (A[1][3] == 1 && A[2][2] == 2 && A[3][1] == 2) return 1;
if (A[1][3] == 2 && A[2][2] == 2 && A[3][1] == 1) return 1;
return 0;
}
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
int Modify(int S, char st, int x, int y)
{
x = 3 * x + y;
if ((S / pw[x]) % 3) return S;
return S + (st == 'M'? 1: 2) * pw[x];
}
int ans;
void dfs(int x, int y, int S)
{
if (a[x][3 * y + 1] == 'O' || a[x][3 * y + 1] == 'M')
S = Modify(S, a[x][3 * y + 1], a[x][3 * y + 2] - '1', a[x][3 * y + 3] - '1');
if (vis[x][y][S]) return ;
vis[x][y][S] = 1;
if (win[S])
{
ans += !Vis[S], Vis[S] = 1;
return;
}
for (int i = 0; i < 4; i++)
{
int X = x + dx[i], Y = y + dy[i];
if (a[X][3 * Y + 1] == '#' || a[X][3 * Y + 1] == '\0') continue;
dfs (X, Y, S);
}
}
int main()
{
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
n = Read();
pw[0] = 1;
for (int i = 1; i <= 9; i++) pw[i] = pw[i - 1] * 3;
for (int i = 0; i < pw[9]; i++)
win[i] = Win(i);
for (int i = 1; i <= n; i++)
scanf ("%s", a[i] + 1);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (a[i][3 * j + 1] == 'B')
dfs(i, j, 0);
printf ("%d", ans);
return 0;
}