AI五子棋_04 大數的快速冪模 Python實現


AI五子棋 第四步

恭喜你到達第四步!

看完之后,你大概了解了公鑰體系。我們來看個例子:

公鑰是:p = (5, 493)
私鑰是:s = (269, 493)

在計算機的世界里所有的信息都是以數字的形式存在的,我的秘密是一個數字327,我要使用上面的秘鑰,利用公鑰體系把它悄悄告訴服務器。

用公鑰加密:message_s = 327^5%493 = 259

這時發送的密信是259,服務器收到這個密信,用私鑰把它解密:

message = 259^269%493 = 327

服務器就得到了我發送的密碼327

如你所見,這里要算很大數的冪,比如

  • 259^269 =
    15053467104180638609029925224281715754907934722117000242777258634551580470140153412220680484519790805381655613724396676705173857597403088184158625857979315135844773789379555623558302521623997025891200138511274625668430519371537168899970181189974554453763372047626759969967395097967860557819356030277519625769400770763586028057179937675570037586939759770083093353841252856161768500859373456878103368167758906830277234018467827167779711890401517630533572921657390139411043964035291456161313073576724327795960183532473671314566884529728682681823059275141138882049683036832736391286971240023524693755814249666381072016621932311414629374478355180074544339

當然我們不需要知道它的結果是什么,我們只需要知道取模后的結果。這種運算在剛剛閱讀的材料中叫做“鍾算”,更普遍的叫法是“模冪”(modular exponentiation),有一個很快的算法。https://www.khanacademy.org/computing/computer-science/cryptography/modarithmetic/a/modular-exponentiation

要求

實現模冪算法,通過服務器的檢驗。

訪問http://2**.2**.**.1**:9012/step_04服務器會給你10個問題,每個問題包含三個數(a,b,c),請給出a^b%c的值。返回值寫入字段ans,10個數字用逗號,隔開,提交到http://2**.2**.**.1**:9012/step_04

提示:注意逗號必須是英文逗號。

待處理信息

  • {"is_success": true, "questions": "[[1336, 9084, 350830992845], [450394869827, 717234262, 9791], [2136, 938408201856, 612752924963], [6026, 754904536976, 5916], [787296602, 305437915, 661501280], [864745305, 6963, 484799723855], [4165, 110707859589, 102613824], [398189032, 723455558974, 794842765789], [974657695, 138141973218, 760159826372], [9034, 7765, 437523243]]"}

Python程序實現

import requests as re
import time
def fastModular(x): #快速冪的實現
	"""x[0] = base """
	"""x[1] = power"""
	"""x[2] = modulus"""
	result = 1
	while(x[1] > 0):
		if(x[1] & 1): # 位運算加快判斷奇偶
			result = result * x[0] % x[2]
		x[1] = int(x[1]/2)
		x[0] = x[0] * x[0] % x[2]
	return result

answer = ''
getHtml = re.get("http://2**.2**.**.1**:9012/step_04/")

start = time.process_time()					# 運算時間戳
for i in eval(getHtml.json()['questions']): # 將帶有'[]'符號的字符串轉換成列表
	answer += str(fastModular(i)) + ','
end = time.process_time()					# 運算時間戳

param = {'ans':answer[:-1]}
print(f"Runing time is { end- start} sec")
getHtml = re.get("http://2**.2**.**.1**:9012/step_04/",params=param)
print(getHtml.text)

>>>
runing time is 0.0 s
{"is_success": true, "message": "please visit http://2**.2**.**.1**:9012/context/eb63fffd85c01a0a5d8f3cadea18cf56"}
>>>

直接運行即可獲得下一步鏈接答案!!

How can we calculate A^B mod C quickly if B is a power of 2 ?

快速冪模的數學基礎

Using modular multiplication rules:

i.e. A^2 mod C = (A * A) mod C = ((A mod C) * (A mod C)) mod C

a^b % c = (a % c)^b % c

(a * b * c) % d = {(a % d) * (c % d) * (b % d)} % d

a^5 % c = (a % c)^5 % c = {(a % c) * (a % c) * (a % c) * (a % c) * (a % c)} % c

一種算法是利用{(a % c) * (a % c) * (a % c) * (a % c) * (a % c)} % c,利用正常求冪次的方法,將變量進去迭代。result = result * a % c這樣會迭代5次,也就是冪次的運算時間復雜度。

注:迭代運算{(result % c) * (a % c)} % c == result * a % c

還有一種就是利用底數和冪次的關系,將冪次除以2,底數平方倍。這個數還是不變的。再加上利用引理就會方便很多。log(power)的時間復雜度。

4^20 mod 11 = 1099511627776 % 11 =1

= 16^10 mod 11 = (16 mod 11)^10 = 5 ^ 10 mod 11

= 25 ^ 5 mod 11 = (25 mod 11)^5 = 3 ^ 5 mod 11

9 ^ 2.5 = 9 ^ 2 * 9^(1/2) = 9 ^ 2 * 3 mod 11

上面這個需要平方3變9 再開2次方 9變3,得到結果。簡化后我們發現這種方法可以歸結為,當冪次變成奇數的時候,我們將奇數減一,除以二,底數平方,並乘以底數 進行計算。結果是一樣的。這樣想更簡單。也方便程序實現

3 ^ 5 mod 11 = 9 ^ 2 * 3 mod 11 ( 5-1=4 ,4/2=2 )

= (9 mod 11)^2 mod 11 = 2 ^ 2 *3 mod 11

= 4 ^ 1 * 3 mod 11 = (4 mod 11)^1 * 3 mod 11 = 7^1 * 3 mod 11

= 49^0 *7 *3 mod 11 =21 % 11

=1

奇數減一分成偶數次冪那部分最終都會到0次,結果為1。而分出去的一次冪就是決定結果的關鍵因素。

解題過程

快速冪模的方法,冪的除以二那里可以用Python的位運算加快速度 >>, 但是沒怎么用過,就直接除以二 轉化為int了。程序通過Python請求目標網頁。

因為知道是Json數據,就用 .json() 轉換成字典。

問題的形式是類似嵌套列表的方式的字符串,嘗試用list()轉換,沒有成功,上網搜到 eval() 函數,於是乎轉成功了,變成了嵌套列表

for循環進去,調用快速冪模方法將結果拼接於 answer

再把答案提交上去。得到下一關地址。

后面對運行時間感興趣就加了計時函數。一開始用 time.clock()。Python報錯說是這個方法不能用了以后,給出了一個新的替代,就換上去了。

0.0s

加油吧少年,根據這個博客你也可以寫出一個相對智能的五子棋程序,甚至更強的AI算法!

文章會隨時改動,注意到博客里去看。一些網站會爬取本文章,但是可能會有出入。
https://www.cnblogs.com/asmurmur/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM