目录
前言
入队以来的第一场正式比赛,打的并不算好,但是确实学到了很多东西,也有了不少新体验。
ICPC赛制,但是单人比赛,啃着剩下的题坐在一个地方真煎熬啊……
总共完成3/12题。
Problem A. 下一个
送分签到题,不多赘述。
AC代码
#include <iostream>
using namespace std;
char c;
int main()
{
cin >> c;
if(c >= 'a' && c <= 'y')
{
c += 1;
cout << c;
}
else if (c >= 'A' && c <= 'Y')
{
c += 1;
cout << c;
}else
{
cout << "non-existent";
}
return 0;
}
Problem C. 勇者之塔
题目分析
第一眼看过去,哇!模拟……停停停,数据范围直接把循环模拟劝退,我们需要冷静分析一波。
本题其中几个个比较重要的信息:
- 每一次进入下一层都会回到(1,1)
- 每层大小都一样
- 每次走的步长一样
以及要注意的一点
- 输入数据量有点大,比赛时为了防止TLE最好用scanf
综合来说,这一题并不是很难,是一个模拟题,但是单纯的模拟一定会TLE,所以我们要进行优化。
我们发现在进行前进时要消耗“步数”,而通过对题意进行进一步推理我们又可以发现:
在抵达最后第n层的终点时,前面我们走完的n-1层,每层消耗步数一定是一个定值。
只要想出这一点,这一题的优化方案就出来了:
- 总步数step = (n - 1) * 每层走完消耗步数(stepc) + 第n层走的步数(stepleft);
又因为最后一层走的步数 stepleft < step (简单的推理,不再解释了),我们可以继续优化,:
- n(层数) = step / stepc + 1
- stepleft = step % stepc
- endx(结束行)= stepleft * stepx(x方向步长)+ 1
- endy(结束列)= stepleft * stepy(y方向步长)+ 1
最终的答案就能由这几个简单的式子快速求出☆*: .。. o(≧▽≦)o .。.:*☆
只不过求每层步数的时候要注意,stepc最后应该取min(x方向消耗步数,y方向消耗步数)
因为只要一个方向走出去了,就直接进入下一层了。
AC代码
#include <cstdio>
#include <iostream>
using namespace std;
//比赛的时候看到数据范围,气的我无脑longlong
//比赛时写的代码,如有不足还请指出,这不一定是最优方案
long long int n,m;
long long int task;
long long int stepx,stepy,step;
int main()
{
cin >> n >> m;
cin >> task;
for (int i = 0; i < task; ++i)
{
scanf("%lld%lld%lld", &stepx, &stepy, &step);
if((stepx == 0 && stepy == 0) || step == 0)
{
printf("1 1 1\n");
continue;
}
long long int cnt1,cnt2;
long long int stepc = 214748364700;
if(stepx)
{
cnt1 = ((n - 1) / stepx) + 1;
stepc = min(cnt1, stepc);
}
if(stepy)
{
cnt2 = ((m - 1) / stepy) + 1;
stepc = min(cnt2, stepc);
}
long long int ceng = (step / stepc) + 1;
long long int endx,endy;
endx = 1 + (step % stepc) * stepx;
endy = 1 + (step % stepc) * stepy;
cout << ceng << " " << endx << " " << endy << endl;
}
return 0;
}
Problem G. 简单的数学
看到题目式子的时候差点晕过去,求和+连乘,我就差当场写一个o(n^n)的算法了/_ \
言归正传,这题给的数据范围也是不小,那么在我们用编程语言模拟计算的时候,是不是应该停下来想想,原式可不可以化简呢?
我们知道lcm(a,b) = a*b/gcd(a,b) 别问我为什么,问就是学过(~ ̄▽ ̄)~
所以连乘符号里面算到最后就剩了个 j 。
最后把连乘一换,这不就是 i 的阶乘吗?
照这么算这n项,每一项都是 (i 的阶乘/i 的阶乘) 就是1,而n个1相加,就是n。
最后答案是n?
想到这里,我的心态发生了一内内的变化,因为我大概用了半小时想这题怎么写……
这不是一个输入输出题吗?怎么扯这么多数论的东西?
要不是我提前看过一点,知道lcm(a,b) = a*b/gcd(a,b) 这题还真做不出来(如果真的发生了,赛后我看到这题题解可能会觉得自己真是个废物)
内心吐槽了几百遍之后还是把这破数论题交了……(╯‵□′)╯︵┻━┻
AC代码
#include <iostream>
using namespace std;
int n;
int main()
{
cin >> n;
cout << n;
return 0;
}
总结/心得
第一次参加比赛难免会犯一些奇奇怪怪的小错误,忘开longlong啦,忘了回车啦,读题不仔细啦……
不过还是让我学到了很多东西,首先,跟榜确实重要,至少可以给你一个做题的参考,某些题,大家都做不出来,那就没必要看了;还有就是放平心态,永远相信下一秒不会比这一秒更糟了,不管wa了多少发,最后做出来了,就一定能比少做一题的人名次高。
总的来说成绩虽然不会令人失望,但绝算不上是优秀。
下一次,我会再斩一题!