我正在尝试找到第 n 个二进制回文
I am trying to find the nth binary palindrome
Binary palindromes: numbers whose binary expansion is palindromic.
Binary Palindrome -> 是一个二进制表示为回文的数字。
Here is link to the solution with naive approach
我已经从上面link读到它给出了一个找到第n个二进制回文的公式。我无法理解,因此无法编写解决方案。
def palgenbase2(): # generator of palindromes in base 2
#yield 0
x, n, n2 = 1, 1, 2
m = 1;
while True:
for y in range(n, n2):
s = format(y, 'b')
yield int(s+s[-2::-1], 2)
for y in range(n, n2):
s = format(y, 'b')
yield int(s+s[::-1], 2)
x += 1
n *= 2
n2 *= 2
if n2 > 1000000000:
break
ans = {}
for i,j in enumerate(palgenbase2()):
print i,j
ans[i]=j
with open("output","a") as f:
f.write(ans)
#use the saved output to give answer to query later
#this will work but it takes too much time.
n = int(raw_input())
for c in range(0,n):
z = int(raw_input())
print ans[z]
这是一个 Python 代码,但它会生成所有此类回文。
求程序帮助直接获取第n个二进制回文
如下:
Input -> 1 <= n <= 1000000000
Function -> f(n)
output -> nth binary palindrome.
我们可以使用提到的公式 here 在更短的时间内做到这一点吗?
这是 A006995.
中给出的递归算法的一个相当直接的实现
为了提高效率,我使用位移位来执行二进制求幂:当 x
是一个非负整数时,1 << x
等同于 2 ** x
但速度要快得多(在至少,它在标准 CPython).Python 2 和 Python 3 中都存在。
此外,为了提高递归效率,该函数将先前计算的值存储在字典中。这也让我们可以轻松处理递归公式本身无法处理的n <= 2
。
#!/usr/bin/env python
''' Binary palindromes
Find (non-negative) integers which are palindromes when written in binary
See
and https://oeis.org/A006995
Written by PM 2Ring 2016.09.24
Recursion for n>2: a(n)=2^(2k-q)+1+2^p*a(m), where k:=floor(log_2(n-1)), and p, q and m are determined as follows:
Case 1: If n=2^(k+1), then p=0, q=0, m=1;
Case 2: If 2^k<n<2^k+2^(k-1), then set i:=n-2^k, p=k-floor(log_2(i))-1, q=2, m=2^floor(log_2(i))+i;
Case 3: If n=2^k+2^(k-1), then p=0, q=1, m=1;
Case 4: If 2^k+2^(k-1)<n<2^(k+1), then set j:=n-2^k-2^(k-1), p=k-floor(log_2(j))-1, q=1, m=2*2^floor(log_2(j))+j;
'''
#Fast Python 3 version of floor(log2(n))
def flog2(n):
return n.bit_length() - 1
def binpal(n, cache={1:0, 2:1, 3:3}):
if n in cache:
return cache[n]
k = flog2(n - 1)
b = 1 << k
a, c = b >> 1, b << 1
if n == c:
p, q, m = 0, 0, 1
elif b < n < a + b:
i = n - b
logi = flog2(i)
p, q, m = k - logi - 1, 2, (1 << logi) + i
elif n == a + b:
p, q, m = 0, 1, 1
else:
#a + b < n < c
i = n - a - b
logi = flog2(i)
p, q, m = k - logi - 1, 1, (2 << logi) + i
result = (1 << (2*k - q)) + 1 + (1 << p) * binpal(m)
cache[n] = result
return result
def palgenbase2():
''' generator of binary palindromes '''
yield 0
x, n, n2 = 1, 1, 2
while True:
for y in range(n, n2):
s = format(y, 'b')
yield int(s+s[-2::-1], 2)
for y in range(n, n2):
s = format(y, 'b')
yield int(s+s[::-1], 2)
x += 1
n *= 2
n2 *= 2
gen = palgenbase2()
for i in range(1, 30):
b = next(gen)
c = binpal(i)
print('{0:>2}: {1} {1:b} {2}'.format(i, b, c))
输出
1: 0 0 0
2: 1 1 1
3: 3 11 3
4: 5 101 5
5: 7 111 7
6: 9 1001 9
7: 15 1111 15
8: 17 10001 17
9: 21 10101 21
10: 27 11011 27
11: 31 11111 31
12: 33 100001 33
13: 45 101101 45
14: 51 110011 51
15: 63 111111 63
16: 65 1000001 65
17: 73 1001001 73
18: 85 1010101 85
19: 93 1011101 93
20: 99 1100011 99
21: 107 1101011 107
22: 119 1110111 119
23: 127 1111111 127
24: 129 10000001 129
25: 153 10011001 153
26: 165 10100101 165
27: 189 10111101 189
28: 195 11000011 195
29: 219 11011011 219
如果您需要 运行 在 Python 2 上执行此操作,您将无法使用该 flog2
函数,因为 Python 2 整数没有bit_length
方法。这是另一个版本:
from math import floor, log
def flog2(n):
return int(floor(log(n) / log(2)))
我不会写完整的代码。
让我们检查算法
这些列是:位计数、组合、组合计数
- 1 1 | 1
- 2 11 | 1
- 3 101 111 | 2
- 4 1001 1111 | 2
- 5 10001 10101 11011 11111 |4
- 6 100001 101101 110011 11111 |4
如果你遵循这个系列,你将每两步呈指数增长。令 n 为位计数,其中位计数具有以下组合数量: 2<<((n-1)>>1) 。
现在我不知道是否有可能以接近的形式计算它,但递归速度非常快,因为它是指数的:
设 n 为直到 n-1 位的计数,m 为当前计数
int i,n=0,m=0;
for (i=1;m<nth;i++)
{
n=m;
m+=2<<((i-1)>>1);
}
现在你知道需要多少位了:i
你用 (i+1)/2 位构建一个 char 数组作为 100...0
您以二进制形式添加 (nth-n)-1(-1 因为基于 0)。还有欧普拉!你镜像你的令牌并结束。
示例:您需要 12 元素
您要对 1+1+2+2+4+4 求和。所以你知道你的第 12 个元素有 6 位。
在 5 位之前,您有 10 个元素。所以 12-10=2 2-1=1
你有点像
100(6 位/2)
你添加 1-> 二进制 1
100+1=101
您的第 n 个回文数具有以下形式 101101。它也适用于奇数位。检查奇点 1 和 2 位计数
Binary palindromes: numbers whose binary expansion is palindromic.
Binary Palindrome -> 是一个二进制表示为回文的数字。
Here is link to the solution with naive approach
我已经从上面link读到它给出了一个找到第n个二进制回文的公式。我无法理解,因此无法编写解决方案。
def palgenbase2(): # generator of palindromes in base 2
#yield 0
x, n, n2 = 1, 1, 2
m = 1;
while True:
for y in range(n, n2):
s = format(y, 'b')
yield int(s+s[-2::-1], 2)
for y in range(n, n2):
s = format(y, 'b')
yield int(s+s[::-1], 2)
x += 1
n *= 2
n2 *= 2
if n2 > 1000000000:
break
ans = {}
for i,j in enumerate(palgenbase2()):
print i,j
ans[i]=j
with open("output","a") as f:
f.write(ans)
#use the saved output to give answer to query later
#this will work but it takes too much time.
n = int(raw_input())
for c in range(0,n):
z = int(raw_input())
print ans[z]
这是一个 Python 代码,但它会生成所有此类回文。
求程序帮助直接获取第n个二进制回文
如下:
Input -> 1 <= n <= 1000000000
Function -> f(n)
output -> nth binary palindrome.
我们可以使用提到的公式 here 在更短的时间内做到这一点吗?
这是 A006995.
中给出的递归算法的一个相当直接的实现为了提高效率,我使用位移位来执行二进制求幂:当 x
是一个非负整数时,1 << x
等同于 2 ** x
但速度要快得多(在至少,它在标准 CPython).Python 2 和 Python 3 中都存在。
此外,为了提高递归效率,该函数将先前计算的值存储在字典中。这也让我们可以轻松处理递归公式本身无法处理的n <= 2
。
#!/usr/bin/env python
''' Binary palindromes
Find (non-negative) integers which are palindromes when written in binary
See
and https://oeis.org/A006995
Written by PM 2Ring 2016.09.24
Recursion for n>2: a(n)=2^(2k-q)+1+2^p*a(m), where k:=floor(log_2(n-1)), and p, q and m are determined as follows:
Case 1: If n=2^(k+1), then p=0, q=0, m=1;
Case 2: If 2^k<n<2^k+2^(k-1), then set i:=n-2^k, p=k-floor(log_2(i))-1, q=2, m=2^floor(log_2(i))+i;
Case 3: If n=2^k+2^(k-1), then p=0, q=1, m=1;
Case 4: If 2^k+2^(k-1)<n<2^(k+1), then set j:=n-2^k-2^(k-1), p=k-floor(log_2(j))-1, q=1, m=2*2^floor(log_2(j))+j;
'''
#Fast Python 3 version of floor(log2(n))
def flog2(n):
return n.bit_length() - 1
def binpal(n, cache={1:0, 2:1, 3:3}):
if n in cache:
return cache[n]
k = flog2(n - 1)
b = 1 << k
a, c = b >> 1, b << 1
if n == c:
p, q, m = 0, 0, 1
elif b < n < a + b:
i = n - b
logi = flog2(i)
p, q, m = k - logi - 1, 2, (1 << logi) + i
elif n == a + b:
p, q, m = 0, 1, 1
else:
#a + b < n < c
i = n - a - b
logi = flog2(i)
p, q, m = k - logi - 1, 1, (2 << logi) + i
result = (1 << (2*k - q)) + 1 + (1 << p) * binpal(m)
cache[n] = result
return result
def palgenbase2():
''' generator of binary palindromes '''
yield 0
x, n, n2 = 1, 1, 2
while True:
for y in range(n, n2):
s = format(y, 'b')
yield int(s+s[-2::-1], 2)
for y in range(n, n2):
s = format(y, 'b')
yield int(s+s[::-1], 2)
x += 1
n *= 2
n2 *= 2
gen = palgenbase2()
for i in range(1, 30):
b = next(gen)
c = binpal(i)
print('{0:>2}: {1} {1:b} {2}'.format(i, b, c))
输出
1: 0 0 0
2: 1 1 1
3: 3 11 3
4: 5 101 5
5: 7 111 7
6: 9 1001 9
7: 15 1111 15
8: 17 10001 17
9: 21 10101 21
10: 27 11011 27
11: 31 11111 31
12: 33 100001 33
13: 45 101101 45
14: 51 110011 51
15: 63 111111 63
16: 65 1000001 65
17: 73 1001001 73
18: 85 1010101 85
19: 93 1011101 93
20: 99 1100011 99
21: 107 1101011 107
22: 119 1110111 119
23: 127 1111111 127
24: 129 10000001 129
25: 153 10011001 153
26: 165 10100101 165
27: 189 10111101 189
28: 195 11000011 195
29: 219 11011011 219
如果您需要 运行 在 Python 2 上执行此操作,您将无法使用该 flog2
函数,因为 Python 2 整数没有bit_length
方法。这是另一个版本:
from math import floor, log
def flog2(n):
return int(floor(log(n) / log(2)))
我不会写完整的代码。 让我们检查算法
这些列是:位计数、组合、组合计数
- 1 1 | 1
- 2 11 | 1
- 3 101 111 | 2
- 4 1001 1111 | 2
- 5 10001 10101 11011 11111 |4
- 6 100001 101101 110011 11111 |4
如果你遵循这个系列,你将每两步呈指数增长。令 n 为位计数,其中位计数具有以下组合数量: 2<<((n-1)>>1) 。 现在我不知道是否有可能以接近的形式计算它,但递归速度非常快,因为它是指数的: 设 n 为直到 n-1 位的计数,m 为当前计数
int i,n=0,m=0;
for (i=1;m<nth;i++)
{
n=m;
m+=2<<((i-1)>>1);
}
现在你知道需要多少位了:i
你用 (i+1)/2 位构建一个 char 数组作为 100...0 您以二进制形式添加 (nth-n)-1(-1 因为基于 0)。还有欧普拉!你镜像你的令牌并结束。 示例:您需要 12 元素 您要对 1+1+2+2+4+4 求和。所以你知道你的第 12 个元素有 6 位。 在 5 位之前,您有 10 个元素。所以 12-10=2 2-1=1 你有点像 100(6 位/2) 你添加 1-> 二进制 1 100+1=101 您的第 n 个回文数具有以下形式 101101。它也适用于奇数位。检查奇点 1 和 2 位计数