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
提示:注意逗号必须是英文逗号。
待处理信息
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 * 3 mod 11 = 81^1 * 3 mod 11
= 4 * 3 mod 11 = 12 mod 11
=1
奇数减一分成偶数次幂那部分最终都会到0次(1/2=0),结果为1。而分出去的一次幂就是决定结果的关键因素。
解题过程
快速幂模的方法,幂的除以二那里可以用Python的位运算加快速度 >>
, 但是没怎么用过,就直接除以二 转化为int了。程序通过Python请求目标网页。
因为知道是Json数据,就用 .json()
转换成字典。
问题的形式是类似嵌套列表的方式的字符串,尝试用list()转换,没有成功,上网搜到 eval() 函数,于是乎转成功了,变成了嵌套列表
for循环进去,调用快速幂模方法将结果拼接于 answer
再把答案提交上去。得到下一关地址。
后面对运行时间感兴趣就加了计时函数。一开始用 time.clock()。Python报错说是这个方法不能用了以后,给出了一个新的替代,就换上去了。
0.0s
加油吧少年,根据这个博客你也可以写出一个相对智能的五子棋程序,甚至更强的AI算法!
文章会随时改动,注意到博客里去看。一些网站会爬取本文章,但是可能会有出入。
https://www.cnblogs.com/asmurmur/
大模型时代,文字创作已死。2025年全面停更了,世界不需要知识分享。
如果我的工作对您有帮助,您想回馈一些东西,你可以考虑通过分享这篇文章来支持我。我非常感谢您的支持,真的。谢谢!
作者:Dba_sys (Jarmony)
转载以及引用请注明原文链接:https://www.cnblogs.com/asmurmur/p/15166256.html
本博客所有文章除特别声明外,均采用CC 署名-非商业使用-相同方式共享 许可协议。