2020-09-13:判斷一個正整數是a的b次方,a和b是整數,並且大於等於2,如何求解?
阿新 • • 發佈:2020-09-13
福哥答案2020-09-13:
首先確定b的範圍,b的範圍一定在[2,logN]裡。然後遍歷b,求a的範圍,如果範圍長度等於0,說明這個正整數是a的b次方。
1.遍歷b範圍。二分法求a,a初始範圍是[2,logN]。2的400次方耗時5秒。【有程式碼】
2.遍歷b範圍。優化二分法求a,a初始範圍是[2,上一次a的結果]。2的10000次方耗時5秒。【有程式碼】
3.應該有更優化的方案,暫時沒想到。【無程式碼】
因為用到了大整數,所以用python語言編寫。程式碼如下:
#!/usr/bin/python3 import time from functools import wraps def _get_sqrt_range(num, right, exp=2): """ 求num的exp開方,exp是指數,num是結果。求底數。 Args: num: 大於等於0並且是整數。 right: 大於等於0並且是整數。右邊界。 exp: 大於等於0並且是整數。 Returns: 返回元組,表示一個開方範圍。 Raises: IOError: 無錯誤。 """ left = 1 if num == 0: return 0, 0 if num == 1: return 1, 1 if num == 2 or num == 3: return 1, 2 while True: mid = (left + right) // 2 if mid ** exp > num: right = mid if left ** exp == num: return left, left if left + 1 == right: return left, right elif mid ** exp < num: left = mid if right ** exp == num: return right, right if left + 1 == right: return left, right if mid == 1: return 1, 2 else: return mid, mid def get_log_range(num, basenum): """ 求對數範圍。 Args: num: 數,大於等於1並且是整數。 basenum: 底數,大於等於2並且是整數。 Returns: 返回結果。對數範圍。 Raises: IOError: 無錯誤。 """ if num == 1: return 0, 0 else: n = 0 ism = 0 while num >= basenum: if ism == 0 and num % basenum != 0: ism = 1 n += 1 num //= basenum return n, n + ism def timefn(fn): """計算效能的修飾器""" @wraps(fn) def measure_time(*args, **kwargs): t1 = time.time() result = fn(*args, **kwargs) t2 = time.time() print(f"@timefn: {fn.__name__} took {t2 - t1: .5f} s") return result return measure_time @timefn def is_power1(num): """ 判斷n是否是一個數的冪次方形式。 Args: num: 大於等於0並且是整數。 Returns: 返回結果。true是冪數 Raises: IOError: 無錯誤。 """ if num <= 3: return False else: log_range = get_log_range(num, 2) if log_range[0] == log_range[1]: return True expmax = log_range[0] expmin = 2 exp = expmin sqrt = 0 right = 2 ** (1 + log_range[0] // 2) while exp <= expmax: sqrt = _get_sqrt_range(num, right, exp) # right = sqrt[0]#縮小右邊界範圍 if sqrt[0] == sqrt[1]: return True if sqrt == (1, 2): return False exp += 1 return False @timefn def is_power2(num): """ 判斷n是否是一個數的冪次方形式。 Args: num: 大於等於0並且是整數。 Returns: 返回結果。true是冪數 Raises: IOError: 無錯誤。 """ if num <= 3: return False else: log_range = get_log_range(num, 2) if log_range[0] == log_range[1]: return True expmax = log_range[0] expmin = 2 exp = expmin sqrt = 0 right = 2 ** (1 + log_range[0] // 2) while exp <= expmax: sqrt = _get_sqrt_range(num, right, exp) right = sqrt[0] # 縮小右邊界範圍 if sqrt[0] == sqrt[1]: return True if sqrt == (1, 2): return False exp += 1 return False if __name__ == "__main__": print("----2的400次方") num = 2 ** 400 + 1 print(is_power1(num)) print(is_power2(num)) print("\r\n----2的10000次方") num = 2 ** 10000 + 1 print(is_power2(num))
執行程式碼結果如下:
***
[評論](https://user.qzone.qq.com/3182319461/blog/1599951713)