A、Odd One Out
跳转原题点击此:A题地址
1、题目大意
给你三个数,其中两个是相等的,问你还有一个不相等的数是多少。
2、题目解析
直接暴力枚举即可,只要找到两个数相等,那么答案就是另一个数。
#include<bits/stdc++.h>
using namespace std;
int T;
int a, b, c;
void solve()
{
cin >> a >> b >> c;
if(a == b)
cout << c << endl;
else if(a == c)
cout << b << endl;
else
cout << a << endl;
}
int main()
{
cin >> T;
while (T--)
{
solve();
}
return 0;
}
B、Not Quite Latin Square
跳转原题点击此:B题地址
1、题目大意
给定一个3X3的矩阵各由3个A、B、C组成,并且每行每列不能相同。这时拿走一个并用\(?\)代替,问你拿走的这个字符是什么。
2、题目解析
因为每次最多9个字符,所以输入的时候统计下,只要哪个字符不等于3个,那答案就是他
#include<bits/stdc++.h>
using namespace std;
int T;
void solve()
{
char f[10][10];
int ff[5] = {0};
for(int i = 1; i <= 3; i++)
{
for(int j = 1; j <= 3;j ++)
{
cin >> f[i][j];
if(f[i][j] != '?')
{
char tmp = f[i][j] - 'A' + 1;
ff[tmp] ++ ;
}
}
}
for(int i = 1; i <= 3; i++)
{
if(ff[i] != 3)
{
cout << char('A' + i - 1) << endl;
return;
}
}
}
int main()
{
cin >> T;
while (T--)
{
solve();
}
return 0;
}
C、Can I Square?
跳转原题点击此:C题地址
1、题目大意
Calin由n个桶,每个桶里面有\(a_i\) 个 \(1 * 1\)积木,问你所有的积木全部用上能否拼成一个正方形。
2、题目解析
只需要判断所有积木加起来能否被完全开方,因为要拼成正方形,所以每个正方形面积就是:1、4、6、...、以此类推。
要注意两个点:1、sqrt只能用于浮点数开方,并且返回的可能有小数,所以要判断;2、double类型的数据范围是-2^1024 ~ +2^1024,比long long 大,所以放心全部累加吧。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int T;
int n;
double f[N];
void solve()
{
cin >> n;
double tmp = 0;
for(int i = 1; i <= n; i++)
{
cin >>f[i];
tmp += f[i];
}
ll x = sqrt(tmp); // 去除开方后的小数部分(如果有的话)
if(x * x == tmp) // 如果等于原数据,说明开方后是没有小数的
cout << "YES" << endl;
else
cout << "NO" << endl;
}
int main()
{
cin >> T;
while (T--)
{
solve();
}
return 0;
}
D、Unnatural Language Processing
跳转原题点击此:D题地址
1、题目大意
Lura想创造一种新的语言,该语言包含\(a、e作为v元音\) 和 \(b、c、d作为C辅音\),要求创造的音节只能是 CV 两个字符 或者 CVC 三个字符,当Lura创造好单词后,发现需要用 “.”来将单词分为音节,请你帮他分。
2、题目解析
因为题目保证是肯定有答案的,所以我们从后往前判断,找到符合条件的就通过数组记录下来。例如我们找到V音节的,就需要找到后面是C字节的;找到C字节的,就需要找到第二个C字节的。最后在输出即可。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
int T;
int n;
bool st[N];
void solve()
{
string s;
cin >> n >> s;
memset(st, 0, sizeof st);
int x = 0;
for(int i = s.size() - 1; i >= 0; i--)
{
// 用X记录是找哪种形式,然后找对于音节的头
if(x == 1)
{
if(s[i] == 'b' || s[i] == 'c' || s[i] == 'd')
{
st[i] = true;
x = 0;
continue;
}
}
if(s[i] == 'a' || s[i] == 'e') // 来寻找CV形式的音节
{
x = 1;
continue;
}
else if(s[i] == 'b' || s[i] == 'c' || s[i] == 'd') // 寻找cvc形式的音节
{
x = 1;
continue;
}
}
for(int i = 0; i < s.size(); i++)
{
if(st[i] == 1 && i != 0) // 注意第一个不输入分隔符
cout << "." << s[i];
else
cout << s[i];
}
cout << "\n";
}
int main()
{
cin >> T;
while (T--)
{
solve();
}
return 0;
}
E、Romantic Glasses
跳转原题点击此:E题地址
1、题目大意
有n杯果汁,其中Iulia只喝奇数杯的,她男朋友只喝偶数杯。Iulia想要选中某个区间的果汁,使得该区间的奇数杯果汁总量之和等于偶数杯果汁之和,问你是否存在该区间。
2、题目解析
我们只需要通过map存入奇数杯和偶数杯的某个区间差异,只要差异值重复过,说明肯定存在某个区间相等。
1、那如何更新差异值:即通过sum不断加减奇偶的果汁数;
2、那如何保证该差异值是某个区间的差异值:注意是通过奇偶的相加相减抵消了这种差异:
例如:[6,3,1,3,2]:第一次:sum为6,第二次:sum为3,第三次:sum为4,第四次:sum为1,第五次:sum为3。此时sum为3出现过,说明找到了正确区间。这是因为,第二次sum为3时,到最终重复3,这个从l=3到r=5这个区间的奇数杯和偶数杯果子加减为0,所以重复3。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int T;
int n;
void solve()
{
cin >> n;
vector<ll> a(n + 1);
for(int i = 1; i <= n; i++)
cin >> a[i];
// 即将奇数和偶数杯的果子差异存入mp中
// 只要出现过这种差异,就赋值为1
map<ll, ll> mp;
mp[0] = 1; // 初始差异为0,存入
// 注意开ll,数据比较大
ll sum = 0; // sum是用来表示奇数杯和偶数杯的果子差异
for(int i = 1; i <= n; i++)
{
// 根据奇偶的不同更新差异值
if(i & 1)
sum += a[i];
else
sum -= a[i];
// 只要发现出现的差异曾经出现过,说明肯定存在答案
if(mp[sum] == 1)
{
cout << "YES" << endl;
return;
}
mp[sum] = 1;
}
cout << "NO" << endl;
}
int main()
{
cin >> T;
while (T--)
{
solve();
}
return 0;
}
F、题目
跳转原题点击此:F题地址
1、题目大意
有n个人,这几个人每个人都从各自的起点(\(a_i\))一每次1格的速度到各自的终点(\(b_i\)),并且保证(\(a_i < b_i\) 和 每个人的起点与终点不会有重复)。当两个人相遇时,会打招呼。问你一共打了几次招呼。
2、题目解析
由于起点和终点不会重复 且 速度都是一样的,所以只有当到达某个人的终点时,双方才会打招呼。并且当自己的路程包含了其他的人时,说明打的招呼人数就是包含里的人总和。
所以我们对起点排序,当起点较小时找到他的终点在原始数组的下标(这代表在原始数组排名第几,比他小的就是大的招呼人数)。
注意:代码有点极限,不要用longlong开数组,会超时。
#include<bits/stdc++.h>
using namespace std;
#define _1 first
#define _2 second
typedef pair<int, int>pii;
int T;
int n;
void solve()
{
cin >> n;
vector<pii> a(n); // 注意sort是全部,所以不要多开
vector<int> b(n);
for(int i = 0; i < n; i++)
{
cin >> a[i]._1 >> a[i]._2;
b[i] = a[i]._2;
}
sort(a.begin(), a.end()); // 按照起始位置排序
sort(b.begin(), b.end()); // 按照终点位置排序
long long ans = 0;
for(int i = 0; i < n; i++)
{
int end = a[i]._2;
// lower_bound 找到第一个大于等于end的地址,减去头地址,返回下标
// tmp:表示在该人起点较小时,所有比该人终点小的,都会碰见。
int tmp = lower_bound(b.begin(), b.end(), end) - b.begin();
// 加上的是下标(代表有几个人前面,因为是从0开始,所以无需减一)
ans += tmp;
// 去除该人
b.erase(b.begin() + tmp, b.begin() + tmp + 1);
}
cout << ans << endl;
}
int main()
{
cin >> T;
while (T--)
{
solve();
}
return 0;
}
G、Bicycles
跳转原题点击此:G题地址