Wonderful
For an integer n, we call k>=2 a wonderful base of n, ifall digits of n base k are 1.
Now given a string representing n, you should return the smallest goodbase of n in string format.
Example 1:
Input: "13"
Output: "3"
Explanation: 13 base 3is 111.
Example 2:
Input: "4681"
Output: "8"
Explanation: 4681 base8 is 11111.
Example 3:
Input:"1000000000000000000"
Output:"999999999999999999"
Explanation:1000000000000000000 base 999999999999999999 is 11.
Note:
- The range of n is [3, 10^18].
- The string representing n is always valid and will not have leading zeros.
校赛就这么结束了,虽说带病参赛,但还是情理之中拿了个第一……
题目虽然不难,但是其中也暴露出了很多问题。可能是状态原因或者是什么别的,反正好几道题目思路完全正确,但是却是错了很多次才A了,导致罚时特别多……
除此之外这次比赛中我们的破题速度还是很值的肯定的,在比较短的时间内就几乎把所有题目的算法预料到了。但还是那个不稳的问题,有两到模拟题没有做,还有一个二分答案怎么也a不过……
不管怎么说,都已经过去了,积累经验吧,至少我们这次没有死磕一道题目,哪一道题目WA了一时没发现错误,就先发现做下一道题。当然了,前提是要有题可作。西安的regional邀请赛应该是稳去了,至于成绩的话还是不敢抱太大希望,但是怎么说要保铜争银吧……剩下的时间一起加油吧……生病也不能停止写代码……
现在来说说这道题吧,刚刚和学长确认了,不是原创题,但还是不得不赞一下选题人,弄了这么一道有意思的题目。可以说做题的过程真的是一波三折,挫折此起彼伏啊。首先,看到这题第一反应肯定是要用二分答案的,但是二分的前提是要有单调性。数字n分成某一个进制后,在该进制底下所有位都是1,很显然,当进制和位数确定后,可以加权求得一个数字,将这个数字与n比较。这个加权和就是等比数列的和,在最开始的阶段,我们选择用求和公式来表示。这样就有这样一个方程n=(q^(k+1)-1)/(q-1)。只要求这个方程的解即可,其中q为进制,k为位数。于是我开始寻找单调性,我运用了求导、放缩甚至泰勒展开都想到了,但是还是无法找到单调性,因为这个k其实也是一个关于x的函数,而且它是离散的。
你可能觉得好像已经没辙了(我当时也几乎绝望),突然灵感一来,如果k固定为常数的话,那么这个q是否就有单调性呢?简单求导后发现当k>=2时,方程右边的函数确实是单调递增的。然后发现k的取值范围恰好是[2,log(N)],完美的符合。于是开始敲代码啦……但是敲完之后发现小数据可以过,但是大数据却过不了。又经过一番纠结之后,我发现,当进制比较大的时候求等比数列和的时候会超过算术上限。于是加了一个特判,当n在某个进制下的位数达不到二分要求的位数的时候,不计算和,直接返回偏大。这样看似把大的样例给过了,但是交上去还是WA。于是开始意志的考验了,这道题被放在一边,队友开始码下一题,然而我苦苦寻找着错误。我开始自己构造数据,小的进制都没有问题,当我构造了一个1e8进制的数字的时候,代码开始错了。最后发现,是等比数列求和公式的问题,根据方程n=(q^(k+1)-1)/(q-1),当q=1e8的时候,k最小取2,那么k+1就是等于3了,1e8^3当然超过算数上限了。错误就在于用了求和公式,如果裸的直接求和最高次就只有q^2,这个在可接受的范围之内不会超上限。
最后就是一些细节上的东西了,pow的话,当返回结果比较大的时候会出现误差,所以求次方的时候最好也是人工计算。复杂度的话大概是O(logNlogNlogN),枚举klogN,二分进制logN,计算等比数列和logN。再加上Kase,也几乎刚好在可承受范围内。到后面发现那个检查n在相应进制下的位数那个特判好像可以删掉。具体代码如下: