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  为必胜态(当前玩家必胜)。

  1. 枚举小值找规律

通过枚举 的状态,可发现核心规律: 规律:当且仅当   时,先手必败;否则先手必胜。

参考代码:

  • 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的字符串

思路:

直接计算“同时包含个目标字母”的字符串数较复杂,先计算“所有可能的字符串数”,再减去“不满足条件的字符串数”。

alt 如图所示:

  • 没有限制条件长度为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])