在解决 codechef 上的回文问题时,我编写了一个算法,该算法在超过 10^6 的测试用例上给出了 TLE。因此,在已经解决它的人的带领下,我在 python 中编写了以下代码。
################################################
### http://www.codechef.com/problems/TAPALIN ###
################################################
def pow(b,e,m):
r=1
while e>0:
if e%2==1:
r=(r*b)%m
e=e>>1
b=(b*b)%m
return r
def cal(n,m):
from math import ceil
c=280000002
a=pow(26, int(ceil(n/2)), m)
if(n%2==0):
return ((52*(a-1+m)%m)*c)%m
else:
return ((52*(((a-1+m)*c)%m))%m+(a*26)%m)%m
c=int(raw_input())
m=1000000007
for z in range(c):
print cal(int(raw_input()),m)
pow 函数是从右到左的二进制方法。我不明白的是:
- 值 280000002 是从哪里来的?
- 为什么我们需要执行这么多的 mod 操作?
- 这是我不知道的一些著名算法吗?
几乎每个在 codechef 上提交的代码都使用了这个算法,但我无法破译它的工作原理。任何与该理论的联系将不胜感激。
我仍然无法弄清楚到底发生了什么。任何人都可以为这个公式/算法写一个伪代码吗?也帮助我理解这段代码的时间复杂度。另一件让我吃惊的是,如果我把这段代码写成:
################################################
### http://www.codechef.com/problems/TAPALIN ###
################################################
def modular_pow(base, exponent):
result=1
while exponent > 0:
if (exponent%2==1):
result=(result * base)%1000000007
exponent=exponent >> 1
base=(base*base)%1000000007
return result
c=int(raw_input())
from math import ceil
for z in range(c):
n=int(raw_input())
ans=modular_pow(26, int(ceil(n/2)))
if(n%2==0):
print ((52*((ans)-1+ 1000000007)%1000000007)*280000002)%1000000007
else:
print ((52*((((ans)-1+ 1000000007)*280000002)%1000000007))%1000000007+(ans*26)%1000000007)%1000000007
这将性能从0.6secs 提高到 0.4 secs。尽管最好的代码在 0.0 秒内运行。我很困惑。