语法周赛 Round 12 题解
2024年12月25日大约 5 分钟
A.时区转换
分析
- 难度:简单条件判断,输入时有一些小技巧
- 子任务 1(30 分):口算出答案后直接输出对应的结果即可。
- 子任务 2(30 分):此时需要输入正确的时间,有同学可能会以为需要字符串处理,实际上可以考虑用五个字符,或者直接定义
int a, b; char c;
然后cin >> a >> c >> b;
即可。在输入整数时,程序会读取直到非数字字符为止,前导0
也不会影响正确的数值。然后用一个字符型变量吃掉中间的冒号再输入第二个整数即可。输入完成之后因为保证了时间不会跨越一天,直接输出a - 15
和b
即可,但要注意根据格式给出多余的0
。 - 子任务 3(40 分):有可能会跨越一天时,根据
a
的值确认是否要+ 24
就好。
满分参考代码
此处我还是按照我个人的习惯,对于时间类的问题转换为最小单位后在处理。显然在本题中,“转换为分钟”、“往前数 15 小时”、“转换回小时” 可以直接用 a -= 15; if (a < 0) a += 24;
代替。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a, b;
char c;
cin >> a >> c >> b;
// 转换为分钟
int t = a * 60 + b;
// 往前数 15 小时
t -= 15 * 60;
if (t < 0)
t += 24 * 60;
// 转换回小时
a = t / 60;
b = t % 60;
// 按格式输出
if (a < 10)
cout << "0" << a;
else
cout << a;
cout << ":";
if (b < 10)
cout << "0" << b;
else
cout << b;
return 0;
}
B.每数一位
分析
- 难度:基础循环嵌套及数学找规律
- 子任务 1(30 分):当
为一位数时,直接输入 之和即可。 - 子任务 2(30 分):数据范围很小,直接用
暴力枚举 之内的每个整数,使用题目给出的“求数位和”的代码求出“一位数位和”然后求和即可。 - 子任务 3(40 分):容易发现当数据范围很大时上面的思路会超时,可以考虑先打印出每个数的一位数位和看看规律,很容易发现就是
的循环,直接根据数学规律算出答案即可。注意要用long long
。
分参考代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
long long n;
long long ans;
cin >> n;
ans = 0;
for (long long i = 1; i <= n; i++)
{
// 将 i 变为一位数
long long now = i;
while (now > 9)
{
long long num = 0; // 计算 now 的数位和
while (now > 0)
{
num += now % 10;
now /= 10;
}
now = num;
}
// 算入答案
ans += now;
// cout << i << ":" << now << '\n';
}
cout << ans;
return 0;
}
满分参考代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
long long n;
cin >> n;
long long a = n / 9;
long long b = n % 9;
cout << (a * 45) + (1 + b) * b / 2;
return 0;
}
C.数串质数
分析
- 难度:简单字符串处理及质数判断
- 子任务 1(30 分):此时数串只有三种可能性
10
、1011
、101112
,根据题目描述容易发现答案都是 。 - 子任务 2(30 分):根据题目描述,容易发现
为 时答案为 ,为 时答案为 ,为 时答案都为 , 时答案为 。这题的 分就是一个条件判断的题目。 - 子任务 3(40 分):通过加号把几个数组合成一个字符串后处理即可。也可以用整数的方式,(四位质数必然为一个数的十位开头或者一个数的个位开头,和后面的数字组合形成的)。
满分参考代码 1
#include <bits/stdc++.h>
using namespace std;
int n;
string s;
bool isPrime(int x)
{
if (x < 2)
return false;
for (int i = 2; i * i <= x; i++)
if (x % i == 0)
return false;
return true;
}
int main()
{
cin >> n;
for (int i = 10; i <= n; i++)
{
s += (char)(i / 10 + '0');
s += (char)(i % 10 + '0');
}
//cout << s << "\n";
int cnt = 0;
for (int i = 0; i + 4 - 1 < s.size(); i++)
{
if (s[i] == '0')
continue;
int now = (s[i] - '0') * 1000 +
(s[i + 1] - '0') * 100 +
(s[i + 2] - '0') * 10 +
(s[i + 3] - '0');
if (isPrime(now))
{
cnt++;
//cout << now << "\n";
}
}
cout << cnt << "\n";
return 0;
}
满分参考代码 2
#include<bits/stdc++.h>
using namespace std;
bool prime(int x){
if (x < 2)
return false;
for (int i = 2; i * i <= x; i++)
if (x % i == 0)
return false;
return true;
}
int n,s;
int main(){
cin>>n;
for(int i=10;i<=n-1;i++){
int a = (i/10)*1000+(i%10)*100+((i+1)/10)*10+((i+1)%10)*1;
int b = (i%10)*1000+((i+1)/10)*100+((i+1)%10)*10+((i+2)/10)*1;
if(1000 <= a && a <= 9999 && prime(a))
s++;
if(i+2<=n && 1000 <= b && b <= 9999 && prime(b)){
s++;
}
}
cout<<s;
}
D.四数转盘
分析
- 难度:简单模拟
- 子任务 1(30 分):保证了两个字符串长度都为
,又至少有一个o
,所以直接根据op[0]
的值决定输出B
还是D
即可。 - 子任务 2(30 分):保证了每个字符都要输出,直接专心模拟旋转即可。
- 子任务 3(40 分):在
分的基础上,根据 的值决定是否输出即可。容易发现除了真的去模拟转盘旋转之外,如果把ABCD
对应到0123
,左转右转就是+1/-1
然后对 取余了。
满分参考代码
此处给出真的模拟旋转的代码。
#include <bits/stdc++.h>
using namespace std;
char a[2][2];
string op;
string s;
string ans;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
a[0][0] = 'A', a[0][1] = 'B';
a[1][0] = 'D', a[1][1] = 'C';
cin >> op;
cin >> s;
for (int i = 0; i < op.size(); i++)
{
if (op[i] == 'L')
{
// 逆时针
int temp = a[0][0];
a[0][0] = a[0][1];
a[0][1] = a[1][1];
a[1][1] = a[1][0];
a[1][0] = temp;
}
else if (op[i] == 'R')
{
// 顺时针
int temp = a[0][0];
a[0][0] = a[1][0];
a[1][0] = a[1][1];
a[1][1] = a[0][1];
a[0][1] = temp;
}
if (s[i] == 'o')
ans += a[0][0];
}
cout << ans << "\n";
return 0;
}