classSolution { private: unsignedlonglongstr2ull(string& s){ unsignedlonglong res = 0; for (char c : s) { res *= 10; res += c - '0'; } return res; } public: string smallestGoodBase(string n){ unsignedlonglong num = str2ull(n); for (int i = 64; i >= 2; i--) { unsignedlonglong l = 2; unsignedlonglong r = num; while (l < r) { unsignedlonglong mid = l + ((r - l) >> 1); unsignedlonglong temp = 0; for (int j = 0; j < i; j++) { if ((log(temp) + log(mid)) / log(2) >= 64) { temp = num + 1; break; } else temp = temp * mid + 1; } if (temp > num) r = mid; elseif (temp < num) l = mid + 1; elsereturnto_string(mid); } } return""; } };
里面涉及了一个新学的小技巧:如果一个unsigned long long已经溢出过了,那么必然是不符合答案的,应该直接退出计算然后继续二分下一个答案。那么怎么判断temp和mid相乘后是否溢出过呢?只要这两个数分别对2取对数(即二进制的最高位在哪一位),只要取完对数相加后大于或等于64,就意味着已经溢出并自动取模过了。