據說,李嘉誠的保險櫃密碼是乙個 8 位的數字。他經常更換密碼,但換密碼的規則很簡單,每次都把密碼的數字 * 3,如果有位數溢位,就把最前面的那個數字挪到整個數字末尾加起來 —— 比如 98765432 就會變成 98765432 * 3 = 296296296, 但是這有 9 位, 把最前面的 2 加到末尾, 變成 96296298, 就是新密碼。現在我們偷到了李嘉誠的保險櫃,而且我們知道他最初的密碼是 00000001, 已經迭代了 n 次,求乙個演算法,可以在 o(log n) 的時間內算出密碼。
迭代分析第n次的密碼計算公式:
x0= 0000 0001
x1= (3 * x0) % 108 + (3 * x0) / 108,顯然,x1
< 108
x2= (3 * x1) % 108 + (3 * x1) / 108
= % 108 + / 108
= % 108 + (顯然其值<9) % 108
+ / 108 + / 108
(顯然其值趨於0)
= (32 * x0) % 10(由分配率得)
+ (32 * x0) / 108
+ [(32 * x0) % 108 ] / 108
(趨於0忽略) + 0
= (32 * x0) % 10+ (32 * x0) / 108
x3 = (33
* x0) % 10+ (33 * x0) / 108
以此類推可得:
xn = (3n
* x0) % 10+ (3n * x0) / 108
又因:x0 = 1,所以:xn = 3n % 10+ 3n / 108
關於計算3n:
1、簡單處理的話可以n個3聯乘,時間複雜度o(n),當n較大時比較耗時,此題暫時不考慮大數問題;
2、當n為偶數時,3n=[3(
n/2)]2,當n為奇數時,3n=3*2,時間複雜度o(log n),此為最優解法。
python實現如下:
def g(x):return x % 100000000 + x // 100000000
def f(x):
if x == 1:
return 3
elif x % 2 == 0:
return g(f(x / 2) * f(x / 2))
elif x % 2 == 1:
return g(f(1) * f(x - 1))
if __name__ == '__main__':
print(f(50))
演算法 常見演算法題
演算法題 假如有100個不相同的數,比如從1到100,怎樣使用10次取出其中的10個不同的數字,要求每個數取出的概率一樣 一開始沒有說10次,所以我說,使用乙個random函式,以時間為種子來取,當取出乙個時,做標記,下次再取到這個數時,重新取一次 然後他就說了如果只能夠取10次怎麼辦?一開始我想到...
基礎演算法題
1.一百萬富翁遇到一陌生人,陌生人找他談乙個換錢的計畫,計畫如下 我每天給你十萬,而你每天只需要給我一分錢,第二天我仍然給你十萬元,你給我二分錢,第三天我仍然給你十萬,你給我四分錢.你每天給我的錢是前天的兩倍,直到乙個月 30天 百萬富翁很高興,欣然接受拉這個契約.請編寫乙個程式計算這乙個月中陌生人...
演算法題筆記
1 請給出乙個o nlogn 的演算法,使之能夠找出乙個n個數的序列中最長的單調遞增子串行。這是演算法導論中的一道課後題。解法一 利用求最長公共子串行的思想,將n個數的序列a先排序形成乙個有序的序列b,然後利用動態規劃的思想求a與b的最長公共子串行,得到的最長公共子串行就是所求的解。但是我們知道最長...