现在回想起来,真的不应该去用C++强撸那道应该用Java做的大整数的题目了……
大致题意就是,有一个发气球的机器,然后有n个人,m个座位排成了一个圆圈,总共AC了p道题目,然后机器人每次从某一个位置开始移动,每次花1个时间单位移动一格。每次机器人走到一个人旁边,它就会把这个人已经A的所有题目对应的气球发给他。对于每一道题目,产生的不高兴值是发气球的时间,减去对应A题的时间。然后问,如何选取这个出发点使得总的不高兴值最大。
首先,我们考虑如果发气球机器的起始位置是x,那么对于一道题目,假设解题时间是t,解题人位置是pos,那么其不高兴值是(pos-t)%m-x,这里要注意,如果最后结果小于0,那么要对应加上一个m。那么对于所有的题目,就是对这个单个的式子求个和。现在要求是不高兴值的和最小,那么我们完全可以枚举这个x,然后对应求出每一个和,找到最小的即可。这里很容易证明,x只需要枚举那些可以使得某些题目不高兴值为0的位置。
那么现在问题变成了已知x,如何在O(1)的时间内求出不高兴值的和呢?根据表达式pos-t-x,我们可以发现对于每一个问题pos-t是不变的,因此我们可以提前统计出pos-t的和,用和再减去x乘以A题个数即可。然而,并没有想的那么简单,因为如果说pos-t小于x,那么还要再等一个周期才能发到气球,即不高兴值得再加上m。所以说,每当枚举到一个x,我们还要统计出pos-t的值比当前x小的个数,在最后结果上加上个数乘以m才是当前x对应的不高兴值。至于统计这个,我们排序之后,按顺序离线处理,就可以做到均摊的O(1)的复杂度。总共的复杂度由于排序的存在,是O(NlogN)。代码简短(下次再也不去写c++的大整数了……)具体见代码: