暑假训练12010年湖南省赛题解

Posted biu~跃哥冲冲冲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了暑假训练12010年湖南省赛题解相关的知识,希望对你有一定的参考价值。

写在前面

训练日期:2021.07.19
训练Result: 赛时AC 4题
动力源泉:你想要的东西很贵,你想去的地方很远。

索引导航

Problem A: 汽水瓶

评测传送门
题目详情:

解题思路:
这个题依据题目描述简单模拟即可,注意最后剩余两个瓶子的时候可以向老板借一个空瓶来凑足3个瓶子依然能换一瓶汽水。

AC coding:

#include <map>
#include <set>
#include <string>
#include <queue>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int main()

    int n;
    while (cin >> n) 
        if (n == 0) break;
        int sum = 0;
        while (n >= 3) 
            int tmp = n / 3;
            sum += tmp;
            n %= 3;
            n += tmp;
        
        if (n == 2) sum++;
        cout << sum << endl;
    
    return 0;

Problem B: 弟弟的作业

评测传送门
题目详情:

解题思路:
这个题是字符串处理的常规操做,只有两种运算,加法或减法;二者分开讨论,分别找到 “ + + +” 或 “ − - ”的位置,再结合“ = = =”的位置,对字符串进行分割,分离出加数,被加数,和(或减数,被减数,差),将字符型转换成整型,进行相应的运算,将运算结果再转回字符串型,比较运算结果和算式所给结果是否相同,相同即运算正确。

AC coding:

#include <map>
#include <set>
#include <string>
#include <queue>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int get(string a) 
    int sum = 0;
    for (int i = 0;i < a.size();i++) 
        sum = sum * 10 + a[i] - '0';
    
    return sum;

string trans(int x) 
    int flag = false;
    if (x < 0) flag = true;
    x = abs(x);
    string str = "";
    while (x) 
        char c = '0' + (x % 10);
        str =  c + str;
        x /= 10;
    
    if (flag) str = '-' + str;
    return str;

int main()

    int sum = 0;
    string str; 
    while (cin >> str) 
        bool flag = false;
        for (int i = 0;i < str.size();i++) 
            if (str[i] == '+') flag = true;
        
        if (flag) 
            int idx = str.find('+');
            string a = str.substr(0, idx);
            int idx2 = str.find('=');
            string b = str.substr(idx + 1, idx2 - idx - 1);
            int x = get(a);
            int y = get(b);
            int z = x + y;
            string res = trans(z);
            if (res == str.substr(idx2 + 1, str.size() - idx2)) sum++;
        
        else 
            int idx = str.find('-');
            string a = str.substr(0, idx);
            int idx2 = str.find('=');
            string b = str.substr(idx + 1, idx2 - idx - 1);
            int x = get(a);
            int y = get(b);
            int z = x - y;
            string res = trans(z);
            //cout << str.substr(idx2 + 1, str.size() - idx2) << endl;
            if (res == str.substr(idx2 + 1, str.size() - idx2)) sum++;
        
    
    cout << sum << endl;
    return 0;

Problem C: 数字整除

评测传送门

题目详情:

解题思路:
这个题是大数运算的题目,如果用C++来写的话要用到高精度计算中的大数减法和大数除法(高精除低精)。根据余数是否为 0 0 0 来判断是否整除;
但是对于 p y t h o n python python 来说, p y t h o n python python 支持大数运算,完全不需要模拟,直接计算即可。C++代码写出来相比于 p y t h o n python python代码会稍复杂一点,简便起见,我在这里写了 p y t h o n python python 版本的代码。

AC coding:

#coding:utf-8
while(True):
    n = int(input())
    if n==0:
        break
    g = n%10
    n = n//10
    if (n - (5 * g)) % 17 == 0:
        print(1)
    else:
        print(0)

Problem D: 台球碰撞

评测传送门
题目详情:

解题思路:
运用物理上学到的知识,将台球运动的速度沿水平方向垂直方向分解,这样对于两个方向上的运动可做单独运算,互不影响。对于小球有半径如何处理,只需将原左面的上下左右都裁剪R的宽度。完全非弹性碰撞,碰撞前后无能量损失,表现为速度大小不变。

AC coding:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
int main()

    int l, w, x, y, R, a, v, s;
    while (cin >> l >> w >> x >> y >> R >> a >> v >> s) 
        if (l == 0 && l == w && l == x && l == y && l == R && l == a && l == v && l == s) 
            break;
        
        double L = l - R;
        double W = w - R;//便于分析圆心所在位置

        /*将角度转换成弧度*/
        double alpha = PI * a / 180.0;

        /*将速度沿水平方向和竖直方向分解*/
        double Vx = v * cos(alpha);
        double Vy = v * sin(alpha);
        double X = Vx * s + x;
        double Y = Vy * s + y;
        while (X < R || X > L) 
            if (X < R) X = R + (R - X);
            if (X > L) X = L - (X - L);
        
        while (Y < R || Y > W) 
            if (Y < R) Y = R + (R - Y);
            if (Y > W) Y = W - (Y - W);
        
        printf("%.2lf %.2lf\\n", X, Y);
    

    return 0;

Problem E: 内部收益率

评测传送门
题目详情:

解题思路:
对于题目所给方程的左边的式子,将其看作一个函数,将IRR看作自变量,会发现随着IRR的增大,函数值减小,即左侧的这个函数单调递减。 C R 0 < 0 CR_0 < 0 CR0<0, C R i > 0 ( i > = 1 ) CR_i > 0(i >= 1) CRi>0(i>=1) 当IRR取值大于-1且很接近-1的一个值的时候,会发现分母 1 - IRR会变的非常小,分子大于0,则整体会是很大的一个正数,所以当T无穷大的时候函数一定存在唯一的零点。根据浮点数二分的方法二分出零点即可。不存在多解的情况。
AC coding:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int c[30];
int t;
double qpow(double x,int y)
    double res = 1;
    while(y--) res = res * x;
    return res;

double get(double x)
    double res = c[0];
    for(int i = 1;i <= t;i++)
        res += c[i]/qpow(1 + x,i);
    
    return res;

int main()
    
    while(cin >> t)
        if(t == 0) break;
        for(int i = 0;i <= t;i++)
            cin >> c[i];
        
        double l = -1.0 + 1e-8,r = 1000000000000.0;
        while(r - l > 1e-8)
            double mid = (r + l) / 2.0;
            if(get(mid) >= 0) l = mid;
            else r = mid;
        
        if(fabs(get(l)) < 1e-3) printf("%.2lf\\n",l);
        else printf("No\\n");
    
    
    return 0;

精度这玩意儿不好说,多试几遍就卡对了,哈哈哈。

Problem F: Biggest Number

评测传送门

题目详情:

题目大意:
可以从任意一个数字所在的位置出发,只能沿上下左右四个方向向前走,且只能走数字所在的格子,不能重复走某一个格子。求一条路径长度最长且在在同等路径长度下字典序最大的路径。

解题思路:
DFS+BFS强剪枝。DFS无疑是用来搜索路径的,为了搜索到有效的路径,需要用BFS来提前判断当前点是否还有搜索的必要。判断的关键点是搜索当前点还能走多远,当前搜索的距离加上还能走的距离大于目前所存储答案的长度,直接往下搜;若等于所存储答案的长度,则需将当前点到还能搜索到的最远的点的路径中的所有点存储起来,按逆序排序后和当前DFS搜索序列拼接后与当前所存储的答案的字典序相比较,大于的话,直接搜,否则,不搜索,回退;若小于所存储的答案的长度,直接回退。

AC coding:

#include <string>
#include <cstring>
#include <queue>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 100;
char g[N][N];
int n, m;
int dx[] =  1,0,-1,0 ;
int dy[] =  0,1,0,-1 ;
bool vis[N][N],Vis[N][N];
string res;
PII q[1000010];
bool ok(int x, int y) 
    if (x >= 1 && x <= n && y >= 1 && y <= m) return true;
    else return false;


string bfs(int x, int y) 
    memset(Vis, false, sizeof Vis);
    int hh = 0,tt = -1;
    q[0] =  x,y ;
    tt++;
    Vis[x][y] = true;
    string str = "";
    while (hh <= tt) 
        PII tmp = q[hh++];
        str += g[tmp.first][tmp.second];
        for (int i = 0;i < 4;i++) 
            int xx = tmp.first + dx[i];
            int yy = tmp.second + dy[i];
            if (ok(xx, yy) && isdigit(g[xx][yy]) && !Vis[xx][yy] && !vis[xx][yy]) 
                Vis[xx][yy] = true;
                q[++tt] =  xx,yy ;
            
        
    
    sort(str.begin(), str.end());
    reverse(str.begin(), str.end());
    return str;

void dfs(int x, int y, string sum) 
    vis[x][y] = true;
    sum += g[x][y];
    if (sum.size() > res.size() || (sum.以上是关于暑假训练12010年湖南省赛题解的主要内容,如果未能解决你的问题,请参考以下文章

比赛-暑假训练赛1 (26 Jul, 2018)

2021年暑假康复性训练(Codeforces Round #731 (Div. 3))全题解

2018-暑假留校训练赛

暑假娱乐赛·题解

cumt训练赛题解

16年区域赛训练计划