2018-2019 ACM-ICPC, Asia Jiaozuo Regional Contest


A. Xu Xiake in Henan Province

if-else

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int a, b, c, d;
	std::cin >> a >> b >> c >> d;
	int s = (a > 0) + (b > 0) + (c > 0) + (d > 0);
	if (s == 0) {
		std::cout << "Typically Otaku\n";
	} else if (s == 1) {
		std::cout << "Eye-opener\n";
	} else if (s == 2) {
		std::cout << "Young Traveller\n";
	} else if (s == 3) {
		std::cout << "Excellent Traveller\n";
	} else {
		std::cout << "Contemporary Xu Xiake\n";
	}
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}

E. Resistors in Parallel

题意:选\(1\)和一些质数使得它们的乘积不超过\(n\)。设\(d_i\)为这些质数乘积的因子,则答案为\(\frac{1}{\frac{1}{d_1} + \frac{1}{d_2} + ... + \frac{1}{d_k}}\)。求最小的答案。

应该从小到大选质数,打表发现分母是每个选了的质数加1的乘积。

点击查看代码
import math
N = 10000

primes = []
minp = (N + 1) * [0]
for i in range(2, N + 1) :
	if minp[i] == 0 :
		minp[i] = i
		primes.append(i)
	for p in primes :
		if p * i > N :
			break
		minp[p * i] = p
		if minp[i] == p :
			break;

t = int(input())
while t > 0:
	t -= 1
	n = int(input())
	a = 1
	b = 1
	for p in primes :
		if a * p > n :
			break
		a = a * p
		b = b * (p + 1)

	d = math.gcd(a, b)
	a //= d
	b //= d
	print(str(a)+'/'+str(b))

F. Honeycomb

题意:用一个字符矩阵表示一个蜂巢,蜂巢有\(n \times m\)个房间,有些房间可以到其它房间。求起点到终点最少经过几个房间。

其实就是个\(bfs\)。但建边有点麻烦,需要找一下规律。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

const int N = 6e3 + 10;
char ss[N];

void solve() {
    int n, m;
    scanf("%d%d", &n, &m);
    getchar();
    std::vector<std::string> s(4 * n + 3);
    for (int i = 0; i < 4 * n + 3; ++ i) {
    	gets(ss);	
    	for (int j = 0; ss[j]; ++ j) {
    		s[i] += ss[j];
    	}
    }

    auto get = [&](int i, int j) -> int {
    	return i * m + j;
    };

    std::vector<std::vector<int>> adj(n * m);
    auto addEdge = [&](int u, int v) -> void {
    	adj[u].push_back(v);
    	adj[v].push_back(u);
    };

    int S = -1, T = -1;
    for (int i = 0; i < n; ++ i) {
    	for (int j = 0; j < m; ++ j) {
    		if (j % 2 == 0) {
				int x = i * 5 - i + 2, y = j / 2 * 9 + j / 2 * 3 + 4;
				if (i > 0 && j + 1 < m) {
					if (s[x - 1][y + 3] == ' ') {
						addEdge(get(i, j), get(i - 1, j + 1));
					}
				}

				if (j + 1 < m) {
					if (s[x + 1][y + 3] == ' ') {
						addEdge(get(i, j), get(i, j + 1));
					}
				}

				if (i + 1 < n) {
					if (s[x + 2][y] == ' ') {
						addEdge(get(i, j), get(i + 1, j));
					}
				}	
				if (s[x][y] == 'S') {
					S = get(i, j);
				} else if (s[x][y] == 'T') {
					T = get(i, j);
				}
    		} else {
    			int x = i * 5 - i + 2 + 2, y = (j - 1) / 2 * 9 + (j - 1) / 2 * 3 + 4 + 6;
    			if (j + 1 < m) {
    				if (s[x - 1][y + 3] == ' ') {
    					addEdge(get(i, j), get(i, j + 1));
    				}

    				if (i + 1 < n && s[x + 1][y + 3] == ' ') {
    					addEdge(get(i, j), get(i + 1, j + 1));
    				}
    			}

    			if (i + 1 < n && s[x + 2][y] == ' ') {
    				addEdge(get(i, j), get(i + 1, j));
    			}

				if (s[x][y] == 'S') {
					S = get(i, j);
				} else if (s[x][y] == 'T') {
					T = get(i, j);
				}
    		}
    	}
    }	

    std::queue<int> q;
    std::vector<int> d(n * m, -1);
    d[S] = 1;
    q.push(S);
    while (q.size()) {
    	int u = q.front(); q.pop();
    	for (auto & v : adj[u]) {
    		if (d[v] == -1) {
    			d[v] = d[u] + 1;
    			q.push(v);
    		}
    	}
    }
    printf("%d\n", d[T]);
}

int main() {
	// std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	// std::cin >> t;
	scanf("%d", &t);
	while (t -- ) {
		solve();
	}
	return 0;
}

I. Distance

题意:给你\(n\)个点,依次选点,新加入的点可以增加它和已有所有点之间距离的和的价值。求分别选\([1, n]\)的情况下可以得到的最大值。

思维。
依次从两边选点是最优的。记录一下前缀后缀的贡献模拟就行

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n;
	std::cin >> n;
	std::vector<i64> a(n + 1);
	for (int i = 2; i <= n; ++ i) {
		std::cin >> a[i];
		a[i] += a[i - 1];
	}
	a.push_back(a.back());

	std::vector<i64> ans(n + 1);
	i64 pre = 0, suf = 0;
	for (int i = 1, l = 1, r = n; i <= n; ++ i) {
		if (i & 1) {
			ans[i] = ans[i - 1] + pre + (l - 1) * (a[l] - a[l - 1]) + suf + (n - r) * (a[r + 1] - a[l]);
			pre += (l - 1) * (a[l] - a[l - 1]);
			++ l;
		} else {
			ans[i] = ans[i - 1] + pre + (l - 1) * (a[r] - a[l - 1]) + suf + (n - r) * (a[r + 1] - a[r]);
			suf += (n - r) * (a[r + 1] - a[r]);
			-- r;
		}
	}

	for (int i = 1; i <= n; ++ i) {
		std::cout << ans[i] << " \n"[i == n];
	}
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}
posted @ 2025-05-28 17:32  maburb  阅读(36)  评论(0)    收藏  举报