483. Smallest Good Base

来源:互联网 发布:梦想小镇淘宝充值 编辑:程序博客网 时间:2024/06/06 07:32

For an integer n, we call k>=2 a good base of n, if all digits of n base k are 1.

Now given a string representing n, you should return the smallest good base of n in string format.

The range of n is [3, 10^18].

Example 1:
Input: “13”
Output: “3”
Explanation: 13 base 3 is 111.

这道题刚开始看的时候毫无头绪,感觉唯一合适的思路就是穷举了,从base为2开始一直开始往前试(因为是找最小的基,因此要从小到大的开始试),试到的那个数如果满足条件那么我们就找到了答案。这样的方法显然很笨,绝对的超时。后来看了答案,才恍然大悟,有时候换个角度去思考问题,往往能得到不错的结果。
题目中已经说了,要找到目标数aim的全‘1’表示的base。那么也就是说无论如何最后该aim的表示形式一定是全‘1’的,如果是最小的base那么也就意味着最长的‘1’串。我们可以固定一个‘1’串来找是否有合适的base可以满足,而在固定‘1’串找base的时候可以使用二分查找来节省时间。如果当前的‘1’串都不合适,那么我们就可以减少‘1’串的长度,知道找到为止,这时候‘1’串对应的base一定是最小的base。由于aim的范围是在[3, 10^18],那么‘1’串最长无非是base为2的时候(这里的放缩其实可以适当的放大范围,并不影响整体的复杂度)。

class Solution {public:    string smallestGoodBase(string n) {    unsigned long long tn=(unsigned long long)stoll(n);    unsigned long long x=1;    for (int i=62;i>=2;i--) {        if ((x<<i)<tn) {            unsigned long long cur=mysolve(tn,i);            if (cur!=0) return to_string(cur);        }    }    return to_string(tn-1);    }unsigned long long mysolve(unsigned long long n,int d) {    double tn=(double) n;    unsigned long long right=(unsigned long long)(pow(tn,1.0/d)+1);    unsigned long long left=2;    while (left<=right){        unsigned long long mid=left+(right-left)/2;        unsigned long long sum=1,cur=1;        for (int i=1;i<=d;i++) {            cur*=mid;            sum+=cur;        }        if (sum==n) return mid;        if (sum>n) right=mid-1;        else left=mid+1;    }    return 0;}};
1 0
原创粉丝点击