Atcoder Beginner Contest 422

A

按照题意输出即可。

/*********************************************************************
    程序名:
    作者: xAlec
    日期: 2025-10-01 15:45
    说明: sakana ~
*********************************************************************/
#include <bits/stdc++.h>
#define int long long
using namespace std;

int x, y;
char ch;

signed main() {
	cin >> x >> ch >> y;
	
	if (y < 8) 
		cout << x << ch << y + 1 << '\n';
	else if (x < 8 && y == 8)
		cout << x + 1 << ch << 1 << '\n';
}

B

按照题意模拟即可。

/*********************************************************************
    程序名:
    作者: xAlec
    日期: 2025-10-01 15:45
    说明: sakana ~
*********************************************************************/
#include <bits/stdc++.h>
#define int long long
using namespace std;
int h, w;
char s[25][25];

signed main() {
	
	scanf ("%lld %lld", &h, &w);
	
	for (int i = 1; i <= h; i++)
		scanf ("%s", s[i] + 1);

	bool flag = true;
	for (int i = 1; i <= h; i++) {
		for (int j = 1; j <= w; j++) {
			if (s[i][j] == '#') {
				int cnt = 0;
				cnt += (s[i - 1][j] == '#');
				cnt += (s[i][j - 1] == '#');
				cnt += (s[i + 1][j] == '#');
				cnt += (s[i][j + 1] == '#');
				
				if (cnt != 2 && cnt != 4) {
					flag = false;
					break;
				}
			}
		}
		
		if (!flag)
			break;
	}
	
	if (flag)
		puts("Yes");
	else
		puts("No");
		
	return 0;
}

C

看完题第一反应是 \(\min(cnt_A,cnt_C)\),然后它 WA 了。

严肃思考后发现 \(cnt_B = 0\) 的时候需要特殊考虑,一般化就是因为三个位置要均分,最大的个数只能是 \(\lfloor\frac{n_A + n_B + n_C}{3}\rfloor\)

#include <bits/stdc++.h>
#define int long long
using namespace std;
int test;
int na, nb, nc;

void sol() {
	scanf ("%lld %lld %lld", &na, &nb, &nc);
	
	int up = max(na, nc), down = min(na, nc);
	
	printf ("%lld\n", min(down, (na + nb + nc) / 3));
}

signed main() {
	scanf ("%lld", &test);
	
	while (test--)
		sol();
	
	return 0;
}

D

读完题意可以发现,其实操作是线段树建树。由于总和均分,答案只有可能是 0/1。

#include <bits/stdc++.h>
#define int long long
using namespace std;
constexpr int MAXN = (1 << 20) + 3;
int n, K, a[MAXN], U;

inline int qpow(int x, int exp) {
    int res = 1;
    
    for (; exp; exp /= 2) {
        if (exp & 1)
            res = res * x;
        x = x * x;
    }

    return res;
}

void build(int l, int r, int sum) {
    if (l == r) {
        a[l] = sum;
        return;
    }

    int mid = (l + r) / 2;
    build(l, mid, sum / 2);
    build(mid + 1, r, sum - sum / 2);
}

signed main() {
    scanf ("%lld %lld", &n, &K);

    n = qpow(2, n);
    build(1, n, K);

    for (int i = 1; i < n; i ++) {
        if (a[i] != a[i + 1]) {
            U = 1;
            break;
        }
    }

    printf ("%lld\n", U);
    for (int i = 1; i <= n; i++)
        printf ("%lld%c", a[i], " \n"[i == n]);
    return 0;
}

E

考虑两点 \((x_1, y_1), (x_2,y_2)\) 确定一条直线则有 \(ax_1 + by_1 + c = ax_2 + by_2 + c\),解得 \(\begin{cases}a = y_2 - y_1 \\ b = x_1 - x_2 \\ c = x_2y_1 - x_1y_2\end{cases}\)

考虑一波随机化,每次随机两个点确定一条直线来判,好像概率挺高的,高达 \(25\%\)

#include <bits/stdc++.h>
#define int long long
using namespace std;
random_device seed;
mt19937 rd(seed());
constexpr int MAXN = 5e5 + 10;
int n, a = -1, b = -1, c = -1;
pair<int,int> p[MAXN];

signed main() {
    scanf ("%lld", &n);
    for (int i = 1; i <= n; i++)
        scanf ("%lld %lld", &p[i].first, &p[i].second);
    
    for (int _ = 1; _ <= 100; _++) {
        int x = rd() % n + 1, y = rd() % n + 1;
        // cout << x << ' ' << y << '\n';

        if (x != y) {
            int ta = p[y].second - p[x].second,
                tb = p[x].first - p[y].first,
                tc = p[y].first * p[x].second - p[x].first * p[y].second,
                tot = 0;
            
            for (int i = 1; i <= n; i++) 
                tot += (ta * p[i].first + tb * p[i].second + tc == 0);
            
            if (tot >= n / 2 + 1) {
                a = ta, b = tb, c = tc;
                break;
            }
        }
    }

    if (a == -1 && b == -1 && c == -1)
        printf ("No\n");
    else 
        printf ("Yes\n %lld %lld %lld\n", a, b, c);
    return 0;
}

F

对于 \(u\) 节点的 \(W_u\),如果此时从它开始还有 \(x\) 步走到目的地,则它会被计算 \(x\) 次。

考虑记 \(f_{u,x}\) 表示当前在 \(u\) 节点,还有 \(x\) 步走到目的地的燃料最小花费。有转移:\(f_{v,x - 1} = \max\{f_{u,x} + w_u \times x\}\)

答案即为每个 \(f_{i,0}\)

#include <bits/stdc++.h>
#define FASTIO
#define int long long
using namespace std;
#ifdef FASTIO
	static int ostk[33];
	char buf[1 << 23], *p1, *p2;
	#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 23, stdin), p1 == p2) ? EOF : *p1++)
	
	inline int read() {
		int res = 0, f = 1;
		char ch = getchar();
		
		while (!isdigit(ch))
			f = ch == '-' ? -1 : 1, ch = getchar();
		while (isdigit(ch))
			res = res * 10 + (ch ^ 48), ch = getchar();
		return res * f;
	}
	
	inline void write(int x) {
		int top = 0;
		
		if (x < 0)
			x = -x, putchar('-');
		do {
			ostk[top++] = x % 10;
			x /= 10;
		} while(x);
		while(top)
			putchar(ostk[--top] + '0');
	}
#endif

constexpr int MAXN = 5005;
int n, m, idx;
int head[MAXN], w[MAXN];
int f[MAXN][MAXN];
struct graph {
	int v, nxt;
} e[MAXN << 1];

inline void addedge(int u, int v) {
	e[idx].v = v;
	e[idx].nxt = head[u];
	head[u] = idx++;
}

signed main() {
	n = read();
	m = read();
	memset(head, -1, sizeof(head));
	for (int i = 1; i <= n; i++)
		w[i] = read();
	for (int i = 1; i <= m; i++) {
		int u = read(), v = read();
		addedge(u, v), addedge(v, u);
	}
	
	memset(f, 0x3f, sizeof(f));
	
	for (int u = 0; u <= n; u++)
		f[1][u] = 0;
	
	for (int j = n; j >= 1; j--) {
		for (int u = 1; u <= n; u++) {
			for (int i = head[u]; ~i; i = e[i].nxt) {
				int v = e[i].v;
				f[v][j - 1] = min(f[v][j - 1], f[u][j] + w[u] * j);
			}
		}
	}
	
	for (int i = 1; i <= n; i++)
		write(f[i][0]), putchar('\n');
		
	return 0;
}
posted @ 2025-10-10 09:05  xAlec  阅读(5)  评论(0)    收藏  举报