OMRONCorporationProgrammingContest2025(AtCoderBeginnerContest397)
前言
又更新AtCoder Beginner Contes 的题目讲解啦!!
希望能给诸位带来帮助。
话不多说,开始翻译:
A - Thermometer←点击看翻译
这题只需要运用判断语句。
解题思路
体温为N;
- N≧ 38.0 38.0 38.0 ∘ {}^\circ ∘ C:“高烧”,输出1。
- 38.0 38.0 38.0 ∘ {}^\circ ∘ C>N≧ 37.5 37.5 37.5 ∘ {}^\circ ∘ C:“低烧”,输出2。
- N< 37.5 37.5 37.5 ∘ {}^\circ ∘ C:“正常”,输出3。
代码:
#include<bits/stdc++.h>
using namespace std;
int main() {
float n;
cin>>n;
if(n>=38.0)
{
cout<<1<<endl;
}
else if(n>=37.5){
cout<<2<<endl;
}
else{
cout<<3<<endl;
}
return 0;
}
B - Ticket Gate←点击看翻译
方法思路:
看到这题,许多人都会想到用字符串的插入函数insert,但对于初学者来说还有一种简单的思路。
首先分别定义三个变量来存储当前字符串长度、答案、当前判断位置。
通过循环挨个判断字符是否正确,如果正确则向后继续判断(即位置+1),如果错误则答案+1且长度+1,下一次继续访问这个点。当判断完所有字符,如果长度是奇数,则答案+1。
如上图所示↑,现在的位置是奇数应当是i,所以o是错的,则长度+1,答案+1(相当于在o前面插入一个i)。
…
//中间步骤省略
…
最后如下↓
//注意!!!橙色箭头并不是插入!!!!!
代码:
#include<bits/stdc++.h>
using namespace std;
int main() {
string n;
cin>>n;
int ans=0,l;
l=n.size();
for(int i=0,j=1;i<n.size();)
{
if(j==1)
{
if(n[i]=='i')
{
j=0;
i++;
}
else{
j=0;
ans+=1;
l+=1;
}
}
else if(j==0)
{
if(n[i]=='o')
{
j=1;
i++;
}
else{
j=1;
ans+=1;
l+=1;
}
}
//cout<<ans<<' '<<i<<' '<<j<<endl;
}
if(l%2==1)
{
cout<<ans+1;
}
else{
cout<<ans;
}
return 0;
}
C - Variety Split Easy←点击看翻译
解题思路
- 整体统计:首先统计整个数组的元素出现次数,并计算总的不同元素数量(作为初始右子数组的不同数)。
- 动态调整:从左到右遍历每个可能的分割点,将当前元素从右子数组移到左子数组:
- 右子数组更新:若该元素在右子数组只剩一个实例,移除后右子数组的不同数减1。
- 左子数组更新:若该元素首次加入左子数组,左子数组的不同数加1。
- 实时计算最大值:每次移动后,计算左右子数组的不同数之和,并更新最大值。
代码:
#include<bits/stdc++.h>
using namespace std;
int a[300005],b[300005],c[300005]; // a存储原数组,b记录右半元素出现次数,c记录左半元素出现次数
int main() {
int n, x=0, y=0, ans=0; // x:左半不同数,y:右半不同数,ans:答案
cin >> n;
for(int i=1; i<=n; i++) {
cin >> a[i];
if(b[a[i]] == 0) y++; // 首次出现,右半不同数+1
b[a[i]]++; // 统计右半元素出现次数
}
for(int i=1; i<=n-1; i++) { // 遍历分割点i(左半结束位置)
// 处理右半部分
if(b[a[i]] == 1) y--; // 当前元素是右半最后一个,移除后右半不同数-1
// 处理左半部分
if(c[a[i]] == 0) x++; // 当前元素首次加入左半,左半不同数+1
b[a[i]]--; // 从右半移除该元素
c[a[i]]++; // 加入左半
ans = max(ans, x + y); // 更新最大值
}
cout << ans;
return 0;
}
D - Cubes←点击看翻译
为了解决这个问题,我们需要找到两个正整数 ( x ) 和 ( y ) 使得 ( x3 - y3 = N )。通过数学推导和优化,我们可以有效地解决这个问题。
方法思路
-
数学推导:利用立方差公式 x3 - y3 = (x - y)(x2 + xy + y2 ),我们可以将问题转化为寻找两个因数 a 和 b 使得 a * b = N ,其中 a = x - y 和 b = x2 + xy + y2 。
-
因数遍历:遍历所有可能的因数 a (从 1 到 N 的立方根),检查 a 是否为 N 的因数,并计算对应的 b = N / a 。
-
二次方程解:对于每个有效的因数对 (a, b),检查是否存在整数 m 使得 3y2 + 3ay + a2 = b 有正整数解。通过解二次方程并验证解的条件,确定是否存在有效的 y 和 x 。
解决代码
#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
ll cube_root(ll N) {
if (N == 0) return 0;
ll low = 1, high = 1e6; // 因为N最大是1e18,立方根最多是1e6
while (low <= high) {
ll mid = (low + high) / 2;
if (mid > N / (mid * mid)) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return high;
}
int main() {
ll N;
cin >> N;
ll max_a = cube_root(N);
for (ll a = 1; a <= max_a; ++a) {
if (N % a != 0) continue;
ll b = N / a;
if (4 * b < a * a) continue;
ll temp = 4 * b - a * a;
if (temp % 3 != 0) continue;
temp /= 3;
ll m = sqrt(temp);
if (m * m != temp) continue;
if (m <= a) continue;
if ((m - a) % 2 != 0) continue;
ll y = (m - a) / 2;
ll x = (m + a) / 2;
if (y > 0) {
cout << x << " " << y << endl;
return 0;
}
}
cout << -1 << endl;
return 0;
}
代码解释
- cube_root 函数:通过二分法计算 N 的立方根,确定遍历的上限,减少不必要的计算。
- 主循环:遍历所有可能的因数 a 并检查其是否为 N 的因数。对于每个有效的因数对 (a, b) ,验证是否存在符合条件的整数解。
- 条件检查:检查二次方程的解是否为整数,并验证解的正整数条件,最终输出结果或判断无解。
该方法通过数学优化和高效的因数遍历,确保在合理时间内处理大数范围内的输入。
觉得还不错,可以点点红心和关注,欢迎在评论区评论。