暑假训练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.比赛-暑假训练赛1 (26 Jul, 2018)