本期难度适中,比起前几期的FFT和网络流要容易一些,但是需要仔细思考
C - ORXOR
n=20,可以暴力
把数中间的隔板进行状态压缩枚举
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @file : atcoder.py
# @software : PyCharmimport 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 = 0for arr in arr_list:temp = 0for x in arr:temp |= xret ^= tempreturn retdef main():items = sys.version.split()fp = open("in.txt") if items[0] == "3.10.6" else sys.stdinn = int(fp.readline())a = list(map(int, fp.readline().split()))ans = 1 << 60for 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;
}