PDSU-ACM 2024 第四次周赛 题解

目录/题目列表


注:本题解仅供参考

题解中所有代码均省略头文件,以及添加了宏定义#define int long long

代码中std::可以去掉,只要加上“using namespace std;”就行。

G题与并查集维护相关的知识点为并查集的重点


如果有疑问欢迎评论或找本人询问


A 神仙说他也不懂(签到/模拟)

B 树状数组(模拟)

C 回滚莫队(思维)

D LYS博弈(思维)

E 网络流(并查集-板子)

F 最近公共祖先(思维/并查集)

G 树链剖分 (并查集、完全图、思维)


A 神仙说他也不懂(签到/模拟)


题面:


思路:

          按题目的信息,奇数位的字符串输出第0位,偶数位的字符串输出第1位即可。


AC代码:

void solve()
{
    int n;
    std::string s;
    std::cin >> n;
    for (int i = 1; i <= n; i++)
    {
        std::cin >> s;
        if (i % 2)
            std::cout << s[0];
        else
            std::cout << s[1];
    }
}

B 树状数组(模拟)


题面:


思路:

          原本这题其实是前缀和,但想了想也没啥新颖的改法,于是变成普通的遍历求和做法,只需注意保留小数就可以

          根据动量守恒:m1v1=(m1+m2)v2 就可以求出结果,并且注意题目要求的是第i个小球


AC代码:

void solve()
{
    int n, v, q;
    std::cin >> n >> v >> q;
    std::vector<int> a(n + 1, 0LL);
    for (int i = 1; i <= n; i++)
    {
        std::cin >> a[i];
        a[i] += a[i - 1];
    }
    std::cout << std::fixed << std::setprecision(2) << a[1] * v * 1.0 / (a[q]);
}

C 回滚莫队(思维)


题面:


思路:

先看每个Ai代表什么,代表的是相邻两位的和

由提示给出的表盘可知,转n次正好能转一圈

那么A数组就包含了a1+a2,a2+a3,……,an-1+an,a1+an(a代表表盘上原本的数字),

所以A数组的总和,即A1+A2+......An,就等于2  *(a1+a2+.......+an

那么平均数就很好求了

这道题过程中可能会爆long long,所以#define int long long 是个好习惯(仅打比赛上的)


AC代码:


void solve()
{
    int n;
    std::cin >> n;
    int sum = 0;
    for (int i = 1; i <= n; i++)
    {
        int x;
        std::cin >> x;
        sum += x;
    }
    std::cout << (sum / 2) / n << "\n";
}

D LYS博弈(思维)


题面:


思路:

很典的一道思维题,原题为

目描述 根据逆波兰表示法求表达式的值。有效的算符包括+、-、*、/,每个运算对象可以是整数,也可以是另一个逆波兰表达式。假设给定的逆波兰表达式总是有效的,即表达式总会计算出有效数值且不存在除数为0的情况。其中,整数除法只保留整数部分。 PS:代填空 #include<iostream> #include<stdlib.h> #include<cstring> using namespace std; bool isNumber(char* token) {//判断token是否为操作数 //pdsu-c1 //pdsu-c1 } int evalRPN(char** tokens, int tokensSize) {//求逆波兰表达式的值 //pdsu-c2 //pdsu-c2 } int main() { char s[20][20]; char* tokens[20]; int res; //输入逆波兰表达式 int tokensSize = 0; do { cin >> s[tokensSize]; tokens[tokensSize] = s[tokensSize]; tokensSize++; } while (getchar() != '\n'); res = evalRPN(tokens, tokensSize); cout << "表达式值为:\n"; cout << res; } 输入描述 一行输入只包含数字和'+', '-', '*', '/'等字符。 注意,数字包括正数和负数,而且有可能不止一位数字,比如:-110。数字或者字符之间用空格隔开。 输出描述 输出必要的文字说明,主函数已经实现。 在新的一行,输出一个整数代表结果。 样例输入 2 1 + 3 * 样例输出 表达式值为: 9 代填空: #include<iostream> #include<stdlib.h> #include<cstring> using namespace std; bool isNumber(char* token) {//判断token是否为操作数 //pdsu-c1 //pdsu-c1 } int evalRPN(char** tokens, int tokensSize) {//求逆波兰表达式的值 //pdsu-c2 //pdsu-c2 } int main() { char s[20][20]; char* tokens[20]; int res; //输入逆波兰表达式 int tokensSize = 0; do { cin >> s[tokensSize]; tokens[tokensSize] = s[tokensSize]; tokensSize++; } while (getchar() != '\n'); res = evalRPN(tokens, tokensSize); cout << "表达式值为:\n"; cout << res; } 提示 输入:tokens=["10","6","9","3","+","-11","*","/","*","17","+","5","+"] 输出:22解释:该算式转化为常见的中缀表达式为 (10*(6/(9+3)*-11))+17)+5 =(10*(6/(12*-11))+17)+5 =(10*(6/-132)+17)+5 =(10*0)+17)+5 =(0+17)+5 =17+5 =22
10-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值