随笔 - 5  文章 - 0  评论 - 4  阅读 - 344

洛谷P8471 [Aya Round 1 F] 琪露诺的选择题

原题传送门

题目描述

有 2⋅n 道选择题,每题有 A 和 B 两个选项。正确答案可以表示为一个长度为 2⋅n 的字符串。

现在你要构造出一份作答(长度同样为 2⋅n 的字符串),其中恰好有 a 个 A,同时与正确答案相比,你的作答恰好有 e 个错误。如果不存在这样的构造方案,报告无解。

注意:为了方便处理,本题保证 e≤n。

形式化地,给定 n,a,e 和一个长度为 2⋅n 的 01 串 s,你需要构造出一个恰好有 a 个字符是 0 的长度为 2⋅n 的 01 串 p,使得

其中 [] 是 Iverson Bracket,详见「提示/说明」中的「提示」。


输入格式

本题含有多组数据。

  • 第一行输入一个整数 T,表示数据组数。
  • 对于每组数据:
    • 第一行输入三个整数 n,a,e。
    • 第二行输入一个长度为 2⋅n 的字符串,表示答案串。

输出格式

  • 输出共T行
  • 对于每组数据:
    • 若有解,输出一行一个长度为 2⋅n 的字符串,表示你构造的作答串。
    • 若无解,输出一行一个字符串 -1。

说明/提示

数据规模与约定

对于 100% 的数据,有 1≤T≤100,1≤n≤105 ,0≤e≤n,0≤a≤2⋅n。

单组测试点内保证 ∑(2⋅n)≤106

提示

A. Iverson Bracket
Iverson Bracket,是一种用方括号记号,如果方括号内的条件满足则为 1,不满足则为 0。更确切地讲,
.


题目理解

题目需要求有两个

  1. a个A的同时
  2. 有e个错误

大致思路先求出答案串里的"A"和"B"的数量,先按照所需的要求将一定数量的"A"转成"B"或者把一定数量的"B"转成"A",来满足第一个要求,每改变一个就要记录错误数量加一。
为了满足第二个条件,我们需要根据情况来选择:

  1. 将一个正确的"A"改成"B",将一个正确的"B"改成"A",可以做到增加两个错误
  2. 将一个错误的"A"改成"B",将一个错误的"B"改成"A",可以做到减少两个错误

通过上面两个步骤我们发现一次操作会改变两个错误数量,所以在第一步统计完成之后就对已有错误数量与需要的错误数量对比,如果差值的绝对值是奇数则不可能完成,直接输出-1


上C++代码

#include<bits/stdc++.h>
using namespace std;

int t;
char x[2000005];                                        //记录正确答案
char y[2000005];                                        //修改答案
int n, a, e;
bool z[2000005] = { 0 };				//判断对错

int main()
{
	std::ios::sync_with_stdio(false);               //提高输入输出效率
	cin >> t;                                       //t组数据
	while (t--) {
		int wa = 0;
		int A = 0;
		int B = 0;
		cin >> n >> a >> e;
		memset(x, 0, sizeof(x));
		memset(y, 0, sizeof(y));
		memset(z, 0, sizeof(z));
		for (int i = 1; i <= 2 * n; i++) {
			cin >> x[i];
			y[i] = x[i];
			if (x[i] == 'A') A++;            //记录正确答案的A与B的数量
			else B++;
		}

		if (A < a) {                            //正确答案的A少于需要的A
			int h = a - A;
			int flag = 0;
			for (int i = 1; i <= 2 * n; i++) {
				if (y[i] == 'B' && flag < h) {
					y[i] = 'A';
					wa++;
					A++;
					z[i] = 1;
					flag++;
				}
				if (flag == h) break;
			}
		}
		else if (A > a) {                         //正确答案的A大于需要的A
			int h = A - a;
			int flag = 0;
			for (int i = 1; i <= 2 * n; i++) {
				if (y[i] == 'A' && flag < h) {
					y[i] = 'B';
					wa++;
					A--;
					z[i] = 1;
					flag++;
				}
				if (flag == h) break;
			}
		}

		if ((abs(wa - e)) % 2 == 1)  cout << -1;    //如果不能完成直接输出-1

		else {                                      //通过步骤2调整错误数量
			int h = abs(wa - e) / 2;
			int flag1 = 0;
			int flag2 = 0;
			if (wa > e) {

				for (int i = 1; i <= 2 * n; i++) {
					if (z[i] == 1 && y[i] == 'A' && flag1 < h) {
						y[i] = 'B';
						z[i] = 0;
						flag1++;
						continue;
					}
					if (z[i] == 1 && y[i] == 'B' && flag2 < h) {
						y[i] = 'A';
						z[i] = 0;
						flag2++;
						continue;
					}
					if (flag1 == h && flag2 == h) {
						wa = e;
						break;
					}
				}
			}
			else if (wa < e) {
				for (int i = 1; i <= 2 * n; i++) {
					if (z[i] == 0 && y[i] == 'A' && flag1 < h) {
						y[i] = 'B';
						z[i] = 1;
						flag1++;
						continue;
					}
					if (z[i] == 0 && y[i] == 'B' && flag2 < h) {
						y[i] = 'A';
						z[i] = 1;
						flag2++;
						continue;
					}
					if (flag1 == h && flag2 == h) {
						wa = e;
						break;
					}
				}
			}
			if (flag1 != h || flag2 != h) cout << -1;      //如果数量不足以满足需要的错误数量,就直接输出-1
			else for (int i = 1; i <= 2 * n; i++) cout << y[i];    //输出答案
		}
		cout << endl;

	}

	return 0;                //结束!
}
posted on   NaCly__Fish  阅读(44)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示