バイナリ表現が回文である 2 つの与えられた数の間の数の総数を見つけるための最良の方法は何ですか? 私が解決しようとしている問題は、spoj http://www.spoj.com/problems/BINPALI/にあります。
4 に答える
1 つの可能なアプローチは次のとおりです。
1 番目の数値 M の 2 進数表現を取得します。
バイナリ表現で回文である M より大きい最初の数を見つけます
。
For example if M is 10110111, the number shall be 10111101
結果の数値が < M の場合、左の部分文字列を 1 増やしてから、右の部分文字列と一致させます。
Eg. if M is 10000011, the number shall be 10000001 < M , hence number shall be 10011001.
後続の番号を見つけるには、中央から最後に向かってビットをインクリメントします。
10011001
10100101
10111101
11000011
以下のようにspojの問題とコードを解決しました:
#include<iostream>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<string>
using namespace std;
int main()
{
int a,b,t;
cin>>t;
while(t--)
{
cin>>a>>b;
int total=0;
string s="";
while(a<=b)
{
s="";
for(int i=a;i>0;i=i/2)
{
if(i%2)
s+='1';
else
s+='0';
}
string s2="",s3="";
s2=s.substr(0,s.length()/2);
int k=s.length();
if(k%2)
s3=s.substr(s.length()/2+1,s.length());
else
s3=s.substr(s.length()/2,s.length());
reverse(s2.begin(),s2.end());
if(s2==s3)
{
cout<<a<<" ";
total++;
}
a++;
}
if(!total)
cout<<"none"<<endl;
}
return 0;
}
この問題の制限時間は非常に厳しいです。最適化された回文ジェネレーターでさえ、おそらく機能しません。この与えられた整数列には、OEIS で式を使用する必要がある可能性があります。
逆算式もあります。以下のように与えられます。
反転式: b>0 がバイナリ回文の場合、a(n)=b のインデックス n は n=palindromicIndexOf(b)=(((5-(-1)^m)/2) + sum_{ k=1...floor(m/2)} (floor(b/2^k) mod 2)/2^k))*2^floor(m/2)、m=floor(log_2(b) )。
おそらく、与えられた 2 つのインデックスを取得し、シーケンスから最小の n と最大の n を何らかの方法で見つける必要があります。次に、範囲内のシーケンスから n 番目の数値をすべて出力します (最小 n、最大 n)。n 番目の 2 進回文数の各クエリは O(1) 時間であるため、各テスト ケースには O(log(B - A)) の時間が必要です。これは非常に低いですが、数式を機能させる必要があります。:)
このシーケンスのジェネレータ式を実装してください。私はそれを試してみましたが、動作させることができませんでした。:(かなり複雑です。
とにかく参考までに、Python 2.7.5 で最適化された回文ジェネレーターを使用してみましたが、Time Limit Exceeded が発生しました。興味がある場合は、ここにコードがあります。
from itertools import product, repeat
from bisect import insort, bisect
def all_binary_sequences_of_length_(n):
return [''.join(seq) for seq in product('01', repeat=n)]
def main():
binary_palindromes = [0, 1, 3, 5, 7]
for n in xrange(1, 15):
A = all_binary_sequences_of_length_(n)
for a in A:
b = a[::-1]
# Add palindromes of length 2n + 2
insort(binary_palindromes, int((a+b).join('11'), 2))
# Add palindromes of length 2n + 3
insort(binary_palindromes, int((a+'0'+b).join('11'), 2))
insort(binary_palindromes, int((a+'1'+b).join('11'), 2))
t = int(raw_input())
for _ in repeat(0, t):
a, b = map(int, raw_input().split())
start = bisect(binary_palindromes, a - 1)
end = bisect(binary_palindromes, b)
output = [str(binary_palindromes[i]) for i in xrange(start, end)]
if len(output) == 0:
print 'none'
else:
print ' '.join(output)
if __name__ == '__main__':
main()
Python はそれほど高速な言語ではないことは承知していますが、時間制限が 1 秒しかないため、これを解決するには OEIS の数式を使用するしかないと思います。:)
パイソンはパワフル!複雑にしないでください!うーん、ちょっと遅い!
for _ in range(input()):
has = False
x,y = map(int, raw_input().split())
for i in range(x,y+1):
temp = bin(i)
temp = temp[temp.index('b')+1:]
if temp[::-1] == temp:
has = True
print i,
if not has:
print "none"