本文仅分享我考场上的想法

T1旅游/travel

bcoi题目

居然没发现座位号是ABCDF(没有e),应该要扣15分

考场代码(模仿)
#include<bits/stdc++.h>
using namespace std;
int a, c;
string b, d;
int main(){
	freopen("travel.in", "r", stdin);
	freopen("travel.out", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> a >> b >> c >> d;
	string aa = b.substr(0, 2), bb = d.substr(0, 2);
	if (a == c)
	{
		cout << 1;
		if (aa == bb)
		{
			cout << 1;
			if ((b[2] > 'C' && d[2] > 'C') || (b[2] <= 'C' && d[2] <= 'C'))
			{
				cout << 1;
				int x = abs(b[2] - d[2]);
				if (x == 1)
				{
					cout << 1;
				}
				else
				{
					cout << 0;
				}
			}
			else
			{
				cout << "00";
				return 0;
			}
		}
		else
		{
			cout << "000";
			return 0;
		}
	}
	else
	{
		cout << "0000";
	}
	return 0;
}




T2回文串 / string

bcoi题目

考场上想到一种思路(虽然很垃圾,后面回文串判断方法不做赘述),可以发现让串的每一个a[i]除以题目的最大公约数,最后再输出压缩后的答案*最大公约数(数据太阴就过不了,以至于ans6.in过了ans5.in没过)

考场代码(模仿)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 5;
int a[N], n, t, cnt;
char c[N];
string s;
signed main(){
	freopen("string.in", "r", stdin);
	freopen("string.out", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i] >> c[i];
		if (i == 1)t = a[i];
		else t = __gcd(t, a[i]);
	}
	for (int i = 1; i <= n; i++)
	{
		a[i] /= t;
		for (int j = 1; j <= a[i]; j++)
		{
			s += c[i];
		}
	}
	for (int i = 0; i < s.size() / 2; i++)
	{
		if (s[i] != s[s.size() - i - 1])cnt++;
	}
	cout << cnt * t;
	return 0;
}





T3按位与 / and

bcoi题目

考场上第一眼以为是dp,写了一会发现不是,思考了很久但是想不到是什么解法,于是使用了骗分 + dfs(除了特殊性质B其他特殊情况全出)。回看考场上的非正解但可以骗大量分数的思路,我很好奇是当时是怎么想到的,大抵是我鬼脑发动了吧。。。

数据范围:

① 当n <= 20时,dfs

② 当m = 1 时,代表只能选一个,for寻找最大值

③当m = n 时,全选,直接for跑一遍

④当m = 2 时,要选2个,注意到双层for循环未超时直接跑


⑤ 特殊性质A : 所以数字 + 1都是2的正整数次幂,代表化成2进制一定全是1,可以直接输出第m大的数

为什么?

如

3 2
3 8 15

不难看出都是2的正整数次幂,换成2进制为:

0011
0111
1111

聪明的都懂了吧?这些数字都是以若干个1为后缀组成的,这里面选m个数得到&最大,直接把最大的m个拼起来,不过不需要再循环m次, 这个序列直接输出a[m]和从&a[1] ~ a[m]答案是一样的


否则继续使用dfs(万一对了呢)

考场代码(模仿)
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, m, a[N], ans;
bool flag, vis[N];
bool check_A(int x)
{
	if (int(sqrt(x)) * int(sqrt(x)) == x)return 1;
	return 0;
}
void dfs(int x, int cnt, int p)
{
	if (cnt > m)
	{
		ans = max(ans, p);
		return;
	}
	for (int i = 1; i <= n; i++)
	{
		if (!vis[i])
		{
			vis[i] = 1;
			if (p == 0)dfs(i, cnt + 1, a[i]);
			else dfs(i, cnt + 1, (p & a[i]));
			vis[i] = 0;
		}
	}
} 
signed main(){
	freopen("and.in", "r", stdin);
	freopen("and.out", "w", stdout);
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		if (!check_A(a[i] + 1))flag = 1;
	}
	sort(a + 1, a + 1 + n, greater<int>());
	if (flag == 0)//满足特殊性质A 
	{
		cout << a[m];
		return 0;
	}
	
	if (m == 1)//仅选1个 
	{
		cout << a[1];
		return 0;
	}
	if (m == n)//全选 
	{
		int ans = 0; 
		for (int i = 1; i <= n; i++)
		{
			if (i == 1)ans = a[i];
			else ans = ans & a[i];
		}
		cout << ans;
		return 0;
	}
	
	if (m == 2)//选2个 
	{
		int ans = 0; 
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				if (i == j)continue;
				ans = max(ans, (a[i] & a[j]));
			}
		}
		cout << ans;
		return 0;
	}
	
	dfs(1, 1, 0);
	cout << ans;
	return 0;
}




纸牌游戏 / card

bcoi题目

最后一题忘记咋做的了(其实是考场上写得太屎山了模仿不出来,样例1过了样例2没过)

后记

这次感觉比以往难了很多,第一题80-90,第二题应该60-70,第三题50-60,最后一题应该没分,正常应该有200+(在bcoi做了前3题刚好200分)