2025ACMTEAM纳新初赛题解
A:邪王真翔讨厌电路
思路:
按照题意直接模拟,我们只需要用两个变量 构造出
,最后注意保留小数点后两位即可。
参考代码:
- C
#include <stdio.h>
int main()
{
double r1, r2, ans;
scanf("%lf %lf", &r1, &r2);
ans = 1 / (1 / r1 + 1 / r2);
printf("%.2lf", ans);
}
- Cpp
#include <bits/stdc++.h> //此处为c++万能头,包含大多数头文件
using namespace std;
int main()
{
double r1, r2, ans;
cin >> r1 >> r2;
ans = 1 / ((1 / r1 + 1 / r2));
cout << fixed << setprecision(2) << ans;
}
- Python
a, b = map(float, input().split())
ans = 1 / a + 1 / b
res = 1 / ans
print(f'{res:.2f}')
B:WQB的音乐研究
思路:
题意可简化为,给定7个数,判断这7个数是否都是中的一个,如果是输出YES,否则输出NO,按照该意思模拟即可。
参考代码:
- C
#include <stdio.h>
int main()
{
int a[5] = {1, 2, 3, 5, 6};
int Flag = 1; //Flag用于最终判断音节序列是否仅由五声音调组成
for (int i = 0; i < 7; i++)
{
int t;
scanf("%d", &t);
int flag = 0; //flag用于判断单个音节是否是五声音调中的某一个
for (int j = 0; j < 5; j++)
{
if (a[j] == t)
{
flag = 1;
break;
}
}
if (!flag)
Flag = 0;
}
if (Flag)
printf("YES");
else
printf("NO");
}
- Cpp
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a[5] = {1, 2, 3, 5, 6};
bool Flag = true; //Flag用于最终判断音节序列是否仅由五声音调组成
for (int i = 0; i < 7; i++)
{
int t;
cin >> t;
bool flag = false; //flag用于判断单个音节是否是五声音调中的某一个
for (int j = 0; j < 5; j++)
{
if (a[j] == t)
{
flag = true;
break;
}
}
if (!flag)
Flag = false;
}
if (Flag)
cout << "YES";
else
cout << "NO";
}
- Python
a = list(map(int, input().split())) #以列表形式读入数据
b = [1, 2, 3, 5, 6]
flag = True
for i in a:
if i not in b:
flag = False
break
if flag:
print("YES")
else:
print("NO")
C:小亮神爱喝水
思路:
简单数学题,题意可化简为,最后通过程序描述即可。
参考代码:
- C
#include <stdio.h>
int main()
{
double x;
scanf("%lf", &x);
if (x <= 10)
printf("%.2lf", x * 2.5);
else if (x > 10 && x <= 20)
printf("%.2lf", 25 + (x - 10) * 3.8);
else
printf("%.2lf", 25 + 38 + (x - 20) * 5.2);
}
- Cpp
#include <bits/stdc++.h>
using namespace std;
int main()
{
double x;
cin >> x;
if (x <= 10)
cout << fixed << setprecision(2) << x * 2.5;
else if (x > 10 && x <= 20)
cout << fixed << setprecision(2) << 25 + (x - 10) * 3.8;
else
cout << fixed << setprecision(2) << 25 + 38 + (x - 20) * 5.2;
}
- Python
a = float(input())
if a <= 10.0:
print(f'{a * 2.5:.2f}')
elif 10 < a <= 20.0:
print(f'{25 + (a - 10) * 3.8:.2f}')
else:
print(f'{25 + 38 + (a - 20) * 5.2:.2f}')
D:鸡哥与味真族
思路:
简单模拟题,根据题目给的步骤,分别得出每个相乘所需要的因子,最后检索数据范围内合乎规则的数并输出
参考代码:
- C
#include <stdio.h>
int main() {
for (int i = 1000; i < 10000; i++) {
int part1 = i % 1000;
int part2 = i / 1000;
int part3 = i % 100;
int part4 = i / 100;
int part5 = i % 10;
int part6 = i / 10;
if (i == part1 * part2 + part3 * part4 + part5 * part6) {
printf("%d\n", i);
}
}
return 0;
}
- Cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
for(int i=1000;i<10000;i++){
if(i==(i%1000)*(i/1000)+(i%100)*(i/100)+(i%10)*(i/10))cout<<i<<endl;
}
}
- Python
def find_weizhen_numbers(digits):
start = 10**(digits-1)
end = 10**digits
results = []
for n in range(start, end):
s = str(n)
total = 0
for i in range(1, digits):
left = int(s[:i])
right = int(s[i:])
total += left * right
if total == n:
results.append(n)
return results
n = int(input())
for num in find_weizhen_numbers(n):
print(num)
E:maimai太难了
思路:
并不难的题,是一道读题后,看题说话,所有的条件分支题目里都给了,把题读完就能做出来
参考代码:
- C/Cpp
#include <bits/stdc++.h>
using namespace std;
int T;
double acc,score,scoremax,level;
int main()
{
cin>>T;
while(T--)
{
cin>>acc>>score>>scoremax>>level;
if(acc>=97.0000&&acc<=97.9999) cout<<"S"<<" ";
if(acc>=98.0000&&acc<=98.9999) cout<<"S+"<<" ";
if(acc>=99.0000&&acc<=99.4999) cout<<"SS"<<" ";
if(acc>=99.5000&&acc<=99.9999) cout<<"SS+"<<" ";
if(acc>=100.0000&&acc<=100.4999) cout<<"SSS"<<" ";
if(acc>=100.5000&&acc<=101.0000) cout<<"SSS+"<<" ";
double dx = score/scoremax*100;
if(dx>=0.00&&dx<=84.99) cout<<0<<" ";
if(dx>=85.00&&dx<=89.99) cout<<1<<" ";
if(dx>=90.00&&dx<=92.99) cout<<2<<" ";
if(dx>=93.00&&dx<=94.99) cout<<3<<" ";
if(dx>=95.00&&dx<=96.99) cout<<4<<" ";
if(dx>=97.00&&dx<=100.00) cout<<5<<" ";
double xishu = 0;
if(acc>=100.5000)
{
xishu = 22.4;
acc = 100.5000;
}
else if(acc>=100.4999) xishu = 22.2;
else if(acc>=100.0000) xishu = 21.6;
else if(acc>=99.9999) xishu = 21.4;
else if(acc>=99.5000) xishu = 21.1;
else if(acc>=99.0000) xishu = 20.8;
else if(acc>=98.9999) xishu = 20.6;
else if(acc>=98.0000) xishu = 20.3;
else if(acc>=97.0000) xishu = 20.0;
double rating = floor(xishu*acc*0.01*level);
cout<<rating<<endl;
}
return 0;
}
- Python
T = int(input())
for _ in range(T):
acc, score, scoremax, level = map(float, input().split())
# 输出第一个评级
if 97.0000 <= acc <= 97.9999:
print("S", end=" ")
elif 98.0000 <= acc <= 98.9999:
print("S+", end=" ")
elif 99.0000 <= acc <= 99.4999:
print("SS", end=" ")
elif 99.5000 <= acc <= 99.9999:
print("SS+", end=" ")
elif 100.0000 <= acc <= 100.4999:
print("SSS", end=" ")
elif 100.5000 <= acc <= 101.0000:
print("SSS+", end=" ")
# 计算dx并输出第二个数值
dx = score / scoremax * 100
if 0.00 <= dx <= 84.99:
print(0, end=" ")
elif 85.00 <= dx <= 89.99:
print(1, end=" ")
elif 90.00 <= dx <= 92.99:
print(2, end=" ")
elif 93.00 <= dx <= 94.99:
print(3, end=" ")
elif 95.00 <= dx <= 96.99:
print(4, end=" ")
elif 97.00 <= dx <= 100.00:
print(5, end=" ")
# 计算系数和rating并输出
xishu = 0.0
if acc >= 100.5000:
xishu = 22.4
acc = 100.5000
elif acc >= 100.4999:
xishu = 22.2
elif acc >= 100.0000:
xishu = 21.6
elif acc >= 99.9999:
xishu = 21.4
elif acc >= 99.5000:
xishu = 21.1
elif acc >= 99.0000:
xishu = 20.8
elif acc >= 98.9999:
xishu = 20.6
elif acc >= 98.0000:
xishu = 20.3
elif acc >= 97.0000:
xishu = 20.0
rating = int(xishu * acc * 0.01 * level)
print(rating)
F:斯卡蒂的内心世界
思路:
-
必败态:若当前石子数为 n 时,无论当前玩家取多少颗(
颗),都能让对手进入必胜态,则 n 为必败态(当前玩家必输)。
-
必胜态:若当前石子数为 n 时,存在某种取法(取
颗),能让对手进入必败态,则 n 为必胜态(当前玩家必胜)。
- 枚举小值找规律
通过枚举 的状态,可发现核心规律:
规律:当且仅当
时,先手必败;否则先手必胜。
参考代码:
- Cpp
#include <bits/stdc++.h>
using namespace std;
int T;
int main()
{
cin>>T;
while(T--)
{
int n;
cin>>n;
if(n%3==0){
cout<<"Skadi the Corrupting Heart"<<endl;
}
else{
cout<<"Skadi"<<endl;
}
}
return 0;
}
- C
#include <stdio.h>
int main() {
int T;
// 读取测试用例数量
scanf("%d", &T);
while (T--) {
int n;
// 读取每组的石子数 n
scanf("%d", &n);
// 判断 n 对 3 取余的结果,决定获胜者
if (n % 3 == 0) {
printf("Skadi the Corrupting Heart\n");
} else {
printf("Skadi\n");
}
}
return 0;
}
- Py
# 读取测试用例数量,转换为整数
T = int(input())
# 循环处理每组测试用例
for _ in range(T):
# 读取每组的石子数 n,转换为整数
n = int(input())
# 根据 n%3 的结果判断获胜者并打印
if n % 3 == 0:
print("Skadi the Corrupting Heart")
else:
print("Skadi")
G:Fun的字符串
思路:
直接计算“同时包含个目标字母”的字符串数较复杂,先计算“所有可能的字符串数”,再减去“不满足条件的字符串数”。
如图所示:
- 没有限制条件长度为n的字符串有
种(26个字母,n个位置都有26种可能)
- 不含f/u/n的有
种 (不含一个字母的情况是
,三个字母所以乘三)
- 不含f,u/f,n/u,n的有
种
- 不含f,u,n的有
种
最终得到计算公式:
公式解释:
3×25^n(不含f的也包含了不含f,u f,n f,u,n 同理不含u的包含了不含f,u u,n f,u,n 不含n的也包含了不含f,n u,n f,u,n)
f f,u f,n f,u,n
u f,u u,n f,u,n
n f,n u,n f,u,n
3×24^n(不含f,u/f,n/u,n的也分别包含了不含f,u,n的情况)
f,u f,u,n
f,n f,u,n
u,n f,u,n
在3×25^n的计算过程中多减了一遍f,u f,n u,n所以要加3×24^n
现在的状态不包含:
f u n f,n f,u u,n
还缺少不包含f,u,n的情况,最后再减去23^n
- 使用 long long 类型存储结果,避免因 n 较大导致数值溢出(如
随 n 增长会快速超过 int 类型范围)。
参考代码:
- Cpp
#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;
int main() {
int n;
cin >> n;
ll ans = (ll)pow(26, n) - 3 * (ll)pow(25, n) + 3 * (ll)pow(24, n) - (ll)pow(23, n);
cout << ans << endl;
return 0;
}
- C
#include <stdio.h>
#include <math.h>
typedef long long ll;
ll ans;
int main(){
int n;
scanf("%d",&n);
ans=pow(26,n)-3*pow(25,n)+3*pow(24,n)-pow(23,n);
printf("%ld",ans);
}
- Py
n = int(input())
ans = 26 ** n - 3 * (25 ** n) + 3 * (24 ** n) - (23 ** n)
print(ans)
H:巴巴博弈
思路:
通过样例可发现规律:
当且仅当 时B必胜。
核心思想是巴什博奕,有兴趣自行了解
参考代码:
- Cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
int m,k;
cin>>k>>m;
for(int i=1;i<=1000;i++){
if(i%(m+k)==0)cout<<i<<endl;
}
return 0;
}
- C
#include <stdio.h>
int main() {
int m, k;
scanf("%d%d", &k, &m);
for (int i = 1; i <= 1000; i++) {
if (i % (m + k) == 0) {
printf("%d\n", i);
}
}
return 0;
}
- Py
k, m = map(int, input().split())
for i in range(1, 1001):
if i % (m + k) == 0:
print(i)
I:三角洲之脚本跑刀
思路:
这道题的核心思路是模拟脚本号 "先吐后吃" 的行为,以最大化保险中物品的总价值
- 有 4 格保险,最多只能携带 4 个物品
- 每次搜索会得到若干物品
- 遵循 "先吐后吃" 原则:先将保险中所有物品吐出,再从所有物品(原保险物品 + 新搜索物品)中选择价值最高的 4 个放入保险(因为只需要找4个价值和最大的物品,所以不需要进行删除操作,当物品超过4个时对所有物品价值排序找到前四个即可)
- 计算每次搜索后保险中物品的最大总价值
参考代码:
- Cpp
#include<bits/stdc++.h>
using namespace std;
bool cmp(int a,int b){
return a>b;
}
vector<int>a;
int main(){
int t,n,x;
cin>>t;
while(t--){
cin>>n;
for(int i=0;i<n;i++){
cin>>x;
a.push_back(x);
}
int s=0;
if(a.size()<5) {
for(int i=0;i<a.size();i++){
s+=a[i];
}}
else{
sort(a.begin(),a.end(),cmp);
for(int i=0;i<4;i++){
s+=a[i];
}
}
cout<<s<<endl;
}
}
- C
#include <stdio.h>
// 冒泡排序(降序)
void bubbleSort(int arr[], int size) {
for (int i = 0; i < size - 1; i++) {
// 每轮冒泡将最大元素移到末尾
for (int j = 0; j < size - 1 - i; j++) {
if (arr[j] < arr[j + 1]) { // 降序排列(交换条件与升序相反)
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main() {
int t, n, x;
int a[100000]; // 用数组存储物品价值
int count = 0; // 记录当前物品总数
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
// 读取新物品并加入数组
for (int i = 0; i < n; i++) {
scanf("%d", &x);
a[count++] = x;
}
int s = 0;
// 如果物品数量小于5个,全部相加
if (count < 5) {
for (int i = 0; i < count; i++) {
s += a[i];
}
} else {
// 使用冒泡排序进行降序排序
bubbleSort(a, count);
// 取前4个最大的元素求和
for (int i = 0; i < 4; i++) {
s += a[i];
}
}
printf("%d\n", s);
}
return 0;
}
- Py
t = int(input())
items = [] # 存储所有物品价值
for _ in range(t):
# 读取当前搜索到的物品
parts = list(map(int, input().split()))
n = parts[0]
new_items = parts[1:] # 提取物品价值部分
# 添加新物品到列表
items.extend(new_items)
# 计算结果
if len(items) < 5:
total = sum(items)
else:
# 使用内置排序函数降序排列
sorted_items = sorted(items, reverse=True) # reverse=True表示降序
total = sum(sorted_items[:4])
print(total)
J:三角洲之重生我是航天鼠王
思路:
本题本质是动态规划 0-1 背包问题的经典实现,核心目标是在有限时间内获取最大物资价值。
- 状态定义:用dp[i][j]表示 “考虑前i种物资、使用不超过j分钟时,能获得的最大价值”。
- 状态转移:对第i种物资,有两种选择:
不选该物资:此时最大价值 = 考虑前i-1种物资、用j分钟的最大价值,即dp[i][j] = dp[i-1][j](对应 “收集该物资时间不够,无法选” 的情况)。
选该物资:此时需先留出收集该物资的时间time,剩余j-time分钟用于收集前i-1种物资,总价值 = 前i-1种物资用j-time分钟的价值 + 该物资价值,即dp[i][j] = dp[i-1][j-time] + value。 - 最优解选择:对每种情况,取 “选” 与 “不选” 中的最大值,确保每一步都记录当前条件下的最优解。
示例辅助理解
假设输入 5 种物资的(value, time)如下:(3,1), (4,2), (5,3), (6,4), (7,5)
则 DP 数组的更新过程(关键步骤)如下:
i=1(第 1 种物资:3 价值,1 时间):dp[1][1] = 3(1 分钟选它,价值 3),dp[1][j>=1] = 3。
i=2(第 2 种物资:4 价值,2 时间):dp[2][2] = max(dp[1][2]=3, dp[1][0]+4=4) = 4(2 分钟选第 2 种更优)。
i=3(第 3 种物资:5 价值,3 时间):dp[3][3] = max(dp[2][3]=4, dp[2][0]+5=5) =5(3 分钟选第 3 种更优)。
最终dp[5][5]会计算出 5 分钟内的最大价值(此例中为3+4+7=14,即选第 1、2、5 种物资)。
参考代码:
- Cpp
#include<bits/stdc++.h>
using namespace std;
int main() {
vector<vector<int>> dp(6, vector<int>(6, 0));
for (int i = 1; i <= 5; ++i) { // 循环5次,读取5种物资
int value, time;
cin >> value >> time; // 读取第i种物资的价值和所需时间
for (int j = 0; j <= 5; ++j) { // 遍历所有可能的时间(0~5分钟)
if (time > j) { // 情况1:收集第i种物资的时间不够,无法选
dp[i][j] = dp[i - 1][j];
} else { // 情况2:时间足够,选或不选取最大值
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - time] + value);
}
}
}
cout << dp[5][5] << endl;
return 0;
}
- C
#include <stdio.h>
#include <stdlib.h>
int main() {
int dp[6][6] = {0}; // 初始化为0
for (int i = 1; i <= 5; ++i) {
int value, time;
scanf("%d %d", &value, &time);
for (int j = 0; j <= 5; ++j) { // 时间从0到5
if (time > j) {
// 时间不够,无法选择当前物品
dp[i][j] = dp[i - 1][j];
} else {
// 时间足够,选择最优方案(选或不选)
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - time] + value);
}
}
}
printf("%d\n", dp[5][5]); // 输出结果
return 0;
}
- Py
# 初始化6x6的DP表格,所有元素初始化为0
dp = [[0 for _ in range(6)] for _ in range(6)]
for i in range(5):
value, time = map(int, input().split())
# 遍历所有可能的时间(0到5分钟)
for j in range(6):
if time > j:
# 时间不足,无法选择当前物品,继承上一状态
dp[i][j] = dp[i-1][j]
else:
# 时间充足,选择最优方案(选或不选当前物品)
dp[i][j] = max(dp[i-1][j], dp[i-1][j - time] + value)
# 输出5个物品在5分钟内的最大价值
print(dp[5][5])

京公网安备 11010502036488号