本期难度适中,比起前几期的FFT和网络流要容易一些,但是需要仔细思考
C - ORXOR
n=20,可以暴力
把数中间的隔板进行状态压缩枚举
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @file : atcoder.py
# @software : PyCharm
import bisect
import copy
import sys
from itertools import permutations
from sortedcontainers import SortedList
from collections import defaultdict, Counter, deque
from functools import lru_cache, cmp_to_key
import heapq
import math
sys.setrecursionlimit(100010)
def check(arr_list):
ret = 0
for arr in arr_list:
temp = 0
for x in arr:
temp |= x
ret ^= temp
return ret
def main():
items = sys.version.split()
fp = open("in.txt") if items[0] == "3.10.6" else sys.stdin
n = int(fp.readline())
a = list(map(int, fp.readline().split()))
ans = 1 << 60
for mask in range(1 << n):
b = []
temp = []
for i in range(n):
temp.append(a[i])
if (mask >> i) & 1:
b.append(temp)
temp = []
if len(temp) > 0:
b.append(temp)
ans = min(ans, check(b))
print(ans)
if __name__ == "__main__":
main()
D - Opposite
将坐标为
x
,
y
x,y
x,y的点逆时针旋转
θ
\theta
θ公式
[
x
1
y
1
]
=
[
c
o
s
θ
−
s
i
n
θ
s
i
n
θ
c
o
s
θ
]
[
x
0
y
0
]
\begin {bmatrix} x_1 \\ y_1 \end{bmatrix} = \begin {bmatrix} cos\theta &-sin\theta \\ sin\theta & cos\theta \end{bmatrix} \begin {bmatrix} x_0 \\ y_0 \end{bmatrix}
[x1y1]=[cosθsinθ−sinθcosθ][x0y0]
其实就是欧拉公式在xy坐标系下的变形
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <map>
#include <cmath>
#include <set>
#include <vector>
#include <queue>
#include <unordered_map>
#include <algorithm>
#define LT(x) (x * 2)
#define RT(x) (x * 2 + 1)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
const ll inf = ll(1e15);
const ld pi = 3.1415926535897932384626;
int n;
int main() {
//freopen("in.txt", "r", stdin);
scanf("%d", &n);
int x0, y0, xn, yn;
scanf("%d%d%d%d", &x0, &y0, &xn, &yn);
ld dx0, dy0, dxn, dyn;
dx0 = x0, dy0 = y0, dxn = xn, dyn = yn;
ld cx = (dx0 + dxn) / 2, cy = (dy0 + dyn) / 2;
ld x = dx0 - cx, y = dy0 - cy;
ld sinx = sin(2.0 * pi / n), cosx = cos(2.0 * pi / n);
ld nx = x * cosx - y * sinx + cx, ny = x * sinx + y * cosx + cy;
printf("%.8Lf %.8Lf\n", nx, ny);
return 0;
}
E - Traveler
因为按照颜色顺序,每次必须取完每种颜色最小值与最大值
[
L
,
R
]
[L,R]
[L,R]之间的所有点,从
L
L
L或者
R
R
R进入下一种颜色
显然是个两端点dp的模型
设dp[i][0]是第i种颜色取完之后从L出去(最后一个点是L)的cost最小值,dp[i][1]是从R出去的最小值
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <map>
#include <cmath>
#include <set>
#include <vector>
#include <queue>
#include <unordered_map>
#include <algorithm>
#define LT(x) (x * 2)
#define RT(x) (x * 2 + 1)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<ll> vi;
const ll inf = ll(1e15);
const ld pi = 3.1415926535897932384626;
int n;
vi balls[200020];
ll dp[200020][2];
int main() {
//freopen("in.txt", "r", stdin);
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
int x, c;
scanf("%d%d", &x, &c);
balls[c].push_back(x);
}
for (int i = 0; i <= n; ++i) {
sort(balls[i].begin(), balls[i].end());
}
dp[0][0] = dp[0][1] = 0;
balls[0] = { 0 };
vi last = balls[0];
for (int i = 1; i <= n; ++i) {
if (balls[i].size() == 0) {
dp[i][0] = dp[i - 1][0], dp[i][1] = dp[i - 1][1];
}
else {
int m = balls[i].size(), lm = last.size();
ll l0 = last[0], r0 = last[lm - 1], l1 = balls[i][0], r1 = balls[i][m - 1];
dp[i][0] = min(abs(l0 - r1) + dp[i - 1][0], abs(r0 - r1) + dp[i - 1][1]) + r1 - l1;
dp[i][1] = min(abs(l0 - l1) + dp[i - 1][0], abs(r0 - l1) + dp[i - 1][1]) + r1 - l1;
last = balls[i];
}
}
ll ans = min(abs(last[0]) + dp[n][0], abs(last[last.size() - 1]) + dp[n][1]);
printf("%lld\n", ans);
return 0;
}
F - Construct a Palindrome
把问题改成两边同时出发汇合。由于两边是从 ( 1 , n ) (1,n) (1,n)出发的,设当前的状态为 ( i , j ) (i,j) (i,j),从状态 ( i 0 , j 0 ) (i_0,j_0) (i0,j0)转移到 ( i 1 , j 1 ) (i_1,j_1) (i1,j1)需要满足边 i 0 i 1 i_0i_1 i0i1和边 j 0 j 1 j_0j_1 j0j1是相同字母。求到 ( t , t ) (t,t) (t,t)或者 ( s , t ) (s,t) (s,t)有边的最短路径。修改普通的bfs算法,在转移状态入队列的时候枚举字母即可。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <map>
#include <cmath>
#include <set>
#include <vector>
#include <queue>
#include <unordered_map>
#include <algorithm>
#define LT(x) (x * 2)
#define RT(x) (x * 2 + 1)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
const ll inf = ll(1e15);
const ld pi = 3.1415926535897932384626;
int n, m;
vi g[1002][26];
int f[1002][1002];
bool w[1002][1002];
int main() {
//freopen("in.txt", "r", stdin);
cin >> n >> m;
for (int i = 0; i < m; ++i) {
int u, v;
char c;
cin >> u >> v >> c;
int p = c - 'a';
g[u][p].push_back(v);
g[v][p].push_back(u);
w[u][v] = w[v][u] = 1;
}
memset(f, 0xff, sizeof(f));
f[1][n] = 0;
int ans = 1 << 30;
queue<pii> qu;
qu.push({ 1, n });
while (!qu.empty()) {
pii c = qu.front();
qu.pop();
int u0 = c.first, u1 = c.second;
if (u0 == u1) {
if (f[u0][u1] * 2 <= ans - 1)
ans = f[u0][u1] * 2;
}
if (w[u0][u1]) {
ans = min(ans, f[u0][u1] * 2 + 1);
}
for (int p = 0; p < 26; ++p) {
for (int v0 : g[u0][p]) {
for (int v1 : g[u1][p]) {
if (f[v0][v1] == -1) {
f[v0][v1] = f[u0][u1] + 1;
qu.push({ v0, v1 });
}
}
}
}
}
if (ans > 200000) ans = -1;
printf("%d\n", ans);
return 0;
}