yukicoder No.3037 Restricted Lucas (Hard)
Easyも全く同じコードで通るのでまとめて。
問題概要
Lucas数(0項目が2、1項目が1のフィボナッチ数)のN項目を10億7で割った余りを求めるクエリT個を解いてください。
Easy:「0123456789\"'*/%」が使用禁止でT≦100、1≦N≦2000000000
No.3036 Restricted Lucas (Easy) - yukicoder
Hard:Easyに加えて「+-」も使用禁止。代わりにT≦10に。
No.3037 Restricted Lucas (Hard) - yukicoder
解説
evalって便利ですよね。ってことで頑張って回避して「*、%」の文字コード42と37を作ったら文字列をつなげてはevalに投げることを繰り返します。普通の最小二乗法を利用すればOK。
で、言語にもよりますが、Pythonなら1=int(not None)、0=int(not not None)なので、Easyは文字列の連結が+で出来るので適当に42,37と1000000007を作ってやるだけです。因みにRubyなら0=nil.to_i、-1=~nil.to_iで、宇宙演算子を使って1=nil.to_i<=>~nil.to_iで表現できます。(ただ、evalでの返り値の返し方を知らないので)
Hardになると、+-が使用不可になるので、ビット演算で頑張って42,37,1000000007に加えて「+」の文字コード43も作ります。-は-1をかければいいのでスルー。文字列の連結を行う際は「演算を行うため」という用途に限られる=数字の間に必ず演算子が入るので、例えば"a+b"→"+".join([a,b])みたいに置き換えると幸せになれます。
https://yukicoder.me/submissions/249560
two = int(not None)<<int(not None) cross = ((two<<two)<<two)|(two<<two)|two plus = cross|int(not None) percent = ((two<<two)<<two) | (two<<int(not None)) | int(not None) three = two | int(not None) four = int(not None)<<two seven = four | two | int(not None) sixteen = int(not None)<<four mod = (seven<<((three<<three)|three)) | (seven<<((int(not None)<<four) | seven)) | (three<<((int(not None)<<four)|three)) | (int(not None)<<((int(not None)<<four)|int(not None))) | (three<<(seven<<int(not None))) | ((four|int(not None))<<(four<<int(not None)|int(not None))) | seven def mul(a,b): ret=[] for i in range(len(a)): append=[] for j in range(len(b[int(not(not None))])): add = int(not(not None)) for k in range(len(a[i])): add = eval(chr(plus).join([str(add),chr(cross).join([str(a[i][k]),str(b[k][j])])])) add = eval(chr(percent).join([str(add),str(mod)])) append.append(add) ret.append(append) return ret def solve(n): a = [[int(not None), int(not None)], [int(not None), int(not(not None))]] ret = [[int(not None)],[two]] n = eval(chr(plus).join([str(n),str(~int(not not None))])) while n>int(not(not None)): if n & int(not None): ret = mul(a,ret) a=mul(a,a) n>>=int(not None) return ret[int(not not None)][int(not(not None))] t=int(input()) for i in range(t): n=int(input()) print(solve(n))
感想
本当は載せるつもり無かったんですが、Hard解き終えた後に解説見て「アレ?eval問じゃない?」ってなったので。