这次比赛赛前,有消息称这次比赛的难度是div1,比赛前心里没底。因为自己的学校实力不强,所以这次现场赛资格也来之不易,这是我第一次也是我最后一次打ICPC,所以我不想留下遗憾。
拿到题目的时候也有点畏惧,因为这次比赛的题目都很长,而且是全英文的。为了防止漫无目的的读题而影响做题时间,我们决定跟榜。很快有大佬队过了J题,J题题面有整整一面,硬着头皮上吧。很快读完题就发现,这题是个模拟题。
给出一行C语言语句,求声明变量所占用的字节数,声明的变量或者数组只能有一个。
直接暴力即可。
由于不熟悉Linux操作系统下的编程环境,队友在写这个程序的时候也遇到了一些问题,比如字符串输入没有gets和getline函数(编译器是真的卡),无奈,只能用getchar进行输入了。写程序的速度还算快,草草写完测了几组样例,感觉没问题就提交了,结果不尽如人意,Wrong Answer。然后我们马上找到了一组错误样例,改了程序,重新测试了几组样例,这次应该没问题了,提交上去还是Wrong Answer,心态瞬间崩了。我说干脆直接用%s输入吧,对于变量类型直接判断首字母就行了,long long和long double另作判断。然后队友又重新写了份代码,跑了先前测试的样例,然后提交上去,随后我们就看到了correct原谅色的反馈结果,心态终于正了正。此时我们不敢看排名,因为有两次罚时,名次肯定在老远。
时间已过去将近一个小时。有大佬队开了C题,我们马上转战C题。在读懂题意之后,我们感觉这就是个规律题。
现有一段函数,要求输入一个数组A和一个k,进行一次题目给出的冒泡排序(题目名叫插入排序,过程是冒泡。。),进行k次。
题目的意思是,给你三个数,n,k,mod,问你在1-n的全排列中,有多少个序列运行这个函数之后其最长上升子序列的长度大于等于(n-1),最后的结果对mod取模。1<=n,k<=50,1e8<=mod<=1e9。
给出题目中的程序
function Insertionsort(A,k)
n←the length of A
i←1
while i<=n and i<=k do
j←i
while j>1 and A[j-1]>A[j] do
t←A[j]
A[j]←A[j-1]
A[j-1]←t
j←j-1
end while
i←i+1
end while
end function
样例给的是4 1,4 2,4 3,4 4(省略mod)的,note也比较贴心,把4 1的情况的排列全部列举出来了,观察了一番,并没有找到什么规律。果断写全排列和LIS暴力一下,由于10的全排列就很多了,所以我们打了1 1到8 8表,这一列出来我就发现了规律。分别以n和k为两维,构建了一个矩阵。
1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2
5 6 6 6 6 6 6 6
10 14 24 24 24 24 24 24
17 26 54 120 120 120 120 120
26 42 96 264 720 720 720 720
37 62 150 456 1560 5040 5040 5040
50 86 216 696 2640 10800 40320 40320
纵坐标是n,横坐标是k。
很明显就能看出当n>=k的时候,结果全为n!。对于k>=n这种情况,直接输出n!。然后我们讨论剩下的情况,对于每一列我们求出差分序列。
1
3 4
5 8 18
7 12 30 96
9 16 42 144 600
11 20 54 192 840 4320
13 24 66 240 1080 5760 35280
对于每一列,差分序列构成了一个等差数列,哇!当时我发现这个规律的时候是真的开心。然后我又发现,对于每个序列的,其首项是i * i!,然后差是2 * i!,验证:对于第四列,96 144 192 240,96=4 * 4!,144-96=2 * 4!。由于这个这个题的n和k很小,但是数值很大,而且模数不定,不能一开始就把所有结果打表。我们可以先找出(n,k)这种情况,然后递推下去,直到求出答案。
代码写的飞快,样例测了也没问题,就直接提交了。本以为这题应该能1A,可是又反回了Runtime Error,当时真的是眼前一黑,哪里越界了?鼓起勇气看了下排名,已经掉到100+了,凉凉。突然队友说了句,woc!输入还有个t,然后加了个t的输入,光速提交,本以为这次稳了,结果又是Wrong Answer。规律错了?规律错了?规律错了?我规律找错了?我问,题目中有没有n 随后看到了G题,感觉能写,题目给了12s的限时。 在一个二维空间内,开始给出n个点,和每个点的w值,接下来有m个操作,一共有四种操作,增删改查。然后让输出给次查询结果。查询的时候会给出一个k值和(x,y),如果有点跟他的欧几里得距离等于sqrt(k),那么就加上其w值,最后输出和。对于每次操作有个lastans,真正的坐标是(((x+lastans)%6000+1),((y+lastans)%6000+1))。0<=k<=1e7,1<=x,y,w<=6000,1<=n,m<=1e5。 由于0<=k<=1e7,所以我们可以完全可以把1-1e7所有平方数和拆分出来。也没有多少,最多才3000多。然后就直接暴力,这样复杂度是大概有1e8,12s限时。 按照这种思路,我们写了程序,交上去就TLE了,一直怀疑是方法错了,然后就一直在尝试这一题直到比赛结束。后来问了北航的大佬,他们也是这样写的,但是他们在维护整个图的状态的时候,用的是map!我透!因为这题有1e5的操作数,STL想都没想,就用了邻接矩阵存储。因为平时的训练默认STL很笨重。真的很可惜。这题出了我们应该就有银了,不过事已至此,见好就收吧。 封榜的时候,我们队排名即将掉出100名,比赛是114名之前有奖。最后几分钟的时候由于一直在怼G题,而且没过就很绝望。比赛最终还是结束了,滚榜是真的刺激。从最后一名往上滚,最开始放出来的是封榜之前的排名,以及封榜后的提交记录,但是看不见结果,然后主持人一名一名查看结果,出了题队伍名次就跑到上面去。当看到滚到130名的时候,心想这个奖就稳了。最终我们是铜奖,马马虎虎吧。颁奖结束后,我们就去中街那边吃大餐了。 至此,我的ACM生涯结束了。
Problem G. Best ACMer solves the Hardest Problem
题意
解题思路