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 に提出されたほぼすべてのコードは、まさにこのアルゴリズムを利用していますが、それが機能していることを解読することはできません。理論へのリンクをいただければ幸いです。
これで何が起こっているのかを正確に把握することはまだできません。誰でもこの式/アルゴリズムの疑似コードを書くことができますか? また、このコードの時間の複雑さを理解するのにも役立ちます。私を驚かせるもう 1 つのことは、このコードを次のように記述した場合です。
################################################
### 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.6 秒から 0.4 秒に向上します。ただし、最良のコードは 0.0 秒で実行されます。私はとても混乱しています。