比赛链接:NCPC-2020 with some BAPC/UKIEPC 2020

前期,B,G 队友秒了,K 不难,但是我和队友交流了一会,得出了必须写高精度的结论,上去写,写完后发现结论有点问题,下来改了又上去写,然后才过了。

感觉最大的问题在于结论错了一次,其余没有犯什么大的罪。

但是呢,在看了最短的代码,发现我实际上实现糟糕了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//https://qoj.ac/submission/191620
#include<bits/stdc++.h>
using namespace std;
int n,v,x,m,b,A[1<<20],k;
string s,t;
int main(){
cin>>s>>t;
if(s.size()<t.size())
swap(s,t);
reverse(s.begin(),s.end()),reverse(t.begin(),t.end()),n=s.size(),s=' '+s,t=' '+t+string(n-t.size(),'0');
for(int i=1;i<=n;i++){
x+=s[i]-'0'+t[i]-'0';
if(x>9)
m=i;
x/=10;
}
for(int i=1;i<=m;i++)
if(s[i]>t[i])
v=1;
else if(s[i]<t[i])
v=0;
if(!v)
swap(s,t);
for(int i=1;i<=m;i++){
A[i]=(b-s[i]+'0')%10;
if(A[i]<0)
b=-1,A[i]+=10;
}
for(int i=1;i<=m;i++)
if(A[i])
k=i;
for(int i=k;i;i--)
cout<<A[i];
if(!k)
cout<<0;
cout<<'\n';
}

注意到就是找到最大的符合条件的 $k$ ,然后求出:$10^{k}-(a\mod 10^k)$ ,或者是 $b$ ,而这个位置我们是用 $a,b$ 分别与 $a+b$ 比较去找的,但实际上这个位置就是 $a+b$ 最后一次发生进位的位置。

为啥呢,设 $a=a_n…a_5a_4a_3a_2a_1a_0,b=b_n…b_5b_4b_3b_2b_1b_0$ ,从低位到高位。

如果第 $i$ 位进位了,说明 $a_{i}…a_{0}+b_{i}…b_{0}\ge 10^{i+1}$ ,所以操作的时候不让 $a$ 或者 $b$ 在第 $i$ 位进位,$a+b$ 就一定会在第 $i$ 位进位,所以直接操作 $a,b$ 中的一个让其进位就行了,而且由于 $a_{i}…a_{0}+b_{i}…b_{0}\ge 10^{i+1}$ ,所以另外一个不会退位,所以这一定是合法的,因此这是最优的,就做完了。

但你要说这是我们策略上的问题吗?我觉得不是,只是我们菜了。

C,D 队友秒了,但是这个时候队长上 I 了,我觉得比赛时可以炸,但是中期开炸我觉得很不合理,队长记大过一次,虽然最后过了,但是这个决策确实浪费了很多时间。

反正我觉得很多时候卡题了不如直接跳,逻辑是什么呢?首先红了以后效率会降低,其次可能会错失一些其余机会,比如某个题你很擅长,在干完其余事后头脑清醒了,再回来调试或许效率会更高点。

或者这么说,我个人认为,激进一点就是直接跳,赌跳的收益会比调的收益高,稳健点就调试,都已经会了,只要做法假了,期望的调的时间不会很长,当然,至于两种策略谁激进谁稳健,最终都要根据实际情况来定,不能一概而论。

J 板子,抄了个板子过了。

F 队长神力,将前面的犯罪都弥补了,E 队友神力,队长还秒了个 H 。

那 fw 的我在干嘛呢?我在构造 L ,然后提出一个做法假一个做法,在最后都没有过。

最后来看,总体上而言,过不了 A,L 是实力问题,大的决策问题只有队长的 I 。

但实际上呢?我前期啥事没干,后期构造了半个比赛。

首先,我认为那个构造时间长还没做出来是实力问题,但是前期我其实在偷偷犯罪,我看到 A 的第一眼,我就觉得这是道好题,就很想把他做出来,在想了半天后,发现其不是 dp 而是模拟后,就已经意识到最后的代码可能很难写了。

后面的大部分时间,我一直都在想 A 怎么快速的判断一个方案是合法的,到我开始拿起 L 的时候都没搞出来。

最后在赛后做出来 A 后回头来看,A 或许不难,但也绝对没有这么简单,更别提我当时方向错了,这道题目得先猜出答案再做,而我当时一直在想怎么快速判断一个方案是合法的。

首先,榜上大部分情况下就是可以反映实际的难度,我深刻检讨,或许是在之前的比赛做出来了几道少人的题目,让我以为我在某些题目特别擅长,超过了我自己的平均水平,导致这场比赛直接莽 A 了,但结合所以比赛来看,前面几场就是意外,实际比赛中基本不会发生这种情况,就得一步一个脚印。

其次,我当时还有点私心,我觉得这个题目非常的好,很想自己做出来,但 ACM 是个团队比赛,除非你有超人的能力,否则纯凭个人力量是没法打出好的名次的,团队赛要注重的是配合,如果我那么想独立做题,就应该平时自己多加训,而不是赛时直接去莽题。深刻检讨我自己,希望以后不要在比赛时犯这种错误,多和队友合作交流。

再回头来看 A ,我当时实际上并没有发现答案的一个下界,也没有发现答案就是下界,也没有想出快速模拟的方法,而是一直在想只知道每个区间操作了多少次能否快速判断,这很 ATcoder ,ATcoder 中很多 1000 的题目就是这么做的,所以赛时我没有做出来。

回头来看,这道题目实际就是找下界,证明是下界,然后模拟,如果要快点,就用数据结构加速模拟。不是特别难,是能做的题目,但是我当时的思维就限制在 ATcoder 类型的题目上面,导致根本没有想到,这启示我要多开阔思维,不要把思维局限在某一类方法上。

还记得 NOI D1T2 我就是因为这个原因寄掉的,希望未来不会出现重蹈覆辙的情况,ATcoder 上的题目终究只是一类题目,不能代表所有题目,要想思维开阔要广刷题,多刷题,不能只刷 ATcoder 的题目,我也不能呆在舒适圈里,要多去做些别的题库的题,感受不一样的风格,这样才能变强。