VP Educational Codeforces Round 16


A. King Moves

点击查看代码
void solve() {
    std::string s;
    std::cin >> s;
    if ((s[0] == 'a' || s[0] == 'h') && (s[1] == '1' || s[1] == '8')) {
    	std::cout << 3 << "\n";
    } else if ((s[0] == 'a' || s[0] == 'h') || (s[1] == '1' || s[1] == '8')) {
    	std::cout << 5 << "\n";
    } else {
    	std::cout << 8 << "\n";
    }
}

B. Optimal Point on a Line

中位数定理板子题。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::sort(a.begin(), a.end());
    std::cout << a[n / 2 - (n % 2 == 0)] << "\n";
}

C. Magic Odd Square

题意:构造一个n×n的矩阵,其中[1,n2]之间的数都恰好用一次,使得每行每列每个对角线之和都为奇数。保证n是奇数。

手玩一下发现规律,如果我们把最中间的行和最中间的列都放奇数,就已经满足了,考虑剩下的奇数怎么放。发现我们相当于画了一个坐标轴,如果我们想在其它地方放一个奇数,那么需要对其它三个象限对应的地方也放一个奇数。然后一开始我们用了奇数个奇数,还剩下偶数个奇数,只需要剩下的奇数个数是4的倍数就行了。因为n是奇数,那么总共有n22=n2+12个奇数,用了2n1个,剩下n2+124n22=n24n+32=(n1)(n3)2个,那么这个数一定是4的倍数。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector ans(n, std::vector<int>(n));
    int x = 1, y = 2;
    for (int i = 0; i < n; ++ i) {
    	for (int j = 0; j < n; ++ j) {
    		if (std::abs(i - n / 2) + std::abs(j - n / 2) <= n / 2) {
    			ans[i][j] = x;
    			x += 2;
    		} else {
    			ans[i][j] = y;
    			y += 2;
    		}
    	}
    }

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

D. Two Arithmetic Progressions

题意:对于两个等差序列,求有多少在[L,R]之间的数同时在这两个等差序列里出现过。

根号分治。
考虑两个暴力做法:

  1. 枚举一个等差数列,判断是否在另一个等差序列里出现。
  2. 如果找到一个最小的一个a1k+b1=a2l+b2,那么每次给两边同时加上lcm(a1,a2)等式也成立并且在两个等差序列里出现。那么我们知道这个出现规律是以lcm(a1,a2)为周期的,我们只需要枚举lcm次,就可以找到第一个,然后能计算剩下多少循环。

我们可以在max(a1,a2)1000时用第一个方法,否则用第二个方法。

点击查看代码
void solve() {
	i64 a1, b1, a2, b2, L, R;
	std::cin >> a1 >> b1 >> a2 >> b2 >> L >> R;
	if (a1 < a2) {
		std::swap(a1, a2);
		std::swap(b1, b2);
	}

	if (a1 >= 1000) {
		int ans = 0;
		for (i64 k = std::max(0ll, (L - b1 + a1 - 1) / a1); k * a1 + b1 <= R; ++ k) {
			if ((k * a1 + b1 - b2) % a2 == 0 && (k * a1 + b1 - b2) / a2 >= 0) {
				++ ans;
			}
		}
		std::cout << ans << "\n";
	} else {
		L = std::max({L, b1, b2});
		i64 lcm = a1 / std::gcd(a1, a2) * a2;
		for (i64 i = L; i <= std::min(L + lcm, R); ++ i) {
			if ((i - b1) % a1 == 0 && (i - b2) % a2 == 0) {
				std::cout << (R - i) / lcm + 1 << "\n";
				return;
			}
		}
		std::cout << 0 << "\n";
	}
}

E. Generate a String

题意:一开始你有一个m=0,你要变成n,每次可以使m=m+1,m=m1,花费x,也可以使m=m×2,花费y。求最小代价。

bfs搜索,注意一些剪枝。每个数只可能被入队两次。

点击查看代码
void solve() {
    int n, x, y;
    std::cin >> n >> x >> y;
    std::vector<i64> d(2 * n + 1, 1e18);
    std::queue<std::pair<i64, int>> q;
    d[n] = 0;
    q.push({0, n});
    while (q.size()) {
    	auto [val, u] = q.front(); q.pop();
    	if (u == 0) {
    		continue;
    	}

    	if (val > d[u] || val >= d[0]) {
    		continue;
    	}

    	if (u % 2 == 0 && d[u / 2] > d[u] + y) {
    		d[u / 2] = d[u] + y;
    		q.push({d[u / 2], u / 2});
    	}

    	if (d[u - 1] > d[u] + x) {
    		d[u - 1] = d[u] + x;
    		q.push({d[u - 1], u - 1});
    	}

    	if (u + 1 <= 2 * n && d[u + 1] > d[u] + x) {
    		d[u + 1] = d[u] + x;
    		q.push({d[u + 1], u + 1});
    	}
    }
    std::cout << d[0] << "\n";
}
posted @   maburb  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示