我有兴趣找到一个简单的公式来确定特定bit_num在自然数序列中出现的第n次.具体来说,下表中KN之间的关系是什么.那么,例如,K=123456789123456789123456789中的N是什么,我可以告诉你M50,但N是什么?

length = 5
for K in range(2**length):
    bits = bin(K)[2:].zfill(length)
    M    = K.bit_count() # numbers of "1"s in the binary sequence
    N    = sum(1 for i in range(K) if M==i.bit_count())
    print(f'{K: <2}',bits,M,N)

'''
K  bits  M N
0  00000 0 0
1  00001 1 0
2  00010 1 1
3  00011 2 0
4  00100 1 2
5  00101 2 1
6  00110 2 2
7  00111 3 0
8  01000 1 3
9  01001 2 3
10 01010 2 4
11 01011 3 1
12 01100 2 5
13 01101 3 2
14 01110 3 3
15 01111 4 0
16 10000 1 4
17 10001 2 6
18 10010 2 7
19 10011 3 4
20 10100 2 8
21 10101 3 5
22 10110 3 6
23 10111 4 1
24 11000 2 9
25 11001 3 7
26 11010 3 8
27 11011 4 2
28 11100 3 9
29 11101 4 3
30 11110 4 4
31 11111 5 0
...
'''

所以,我似乎已经解决了一半.看来

N = (K-sum(2**i for i in range(M)).bit_count()

每当N<=M.这似乎是因为,

K = sum(2**i for i in range(M)) + sum(2**(M-1-i) for i in range(N))

再次,每当N<=M.似乎大约有一半的时间出现N<=M.

length = 5
for K in range(2**length):
    bits = bin(K)[2:].zfill(length)
    M    = K.bit_count() # numbers of "1"s in the binary sequence
    N    = sum(1 for i in range(K) if M==i.bit_count())
    if N <= M:
        A = sum(2**i for i in range(M)) + sum(2**(M-1-i) for i in range(N))
        B = (K - sum(2**i for i in range(M))).bit_count()
    else:
        A = '-'
        B = '-'
    print(f'{K: <2}',bits,M,N,A,B)

推荐答案

我不知道Python,所以这是Ruby.该算法应该易于翻译.其 idea 是,对于每个设置位(从小到大),计算该位左侧相同、在该位和其右侧具有相同数量的设置位但没有设置该位的所有数字.

  • 将输入的位从最小到最大.
  • 跟踪看到的集合位和看到的总位.
  • 每次遇到设置位时,使用相同数量的设置位来计算所有数字,但最大设置位(比当前索引)较小.
  • 例如,当达到10100中较小的1时,我们将2加到计数中,因为有2个数字具有1个设置位和较小的最大设置位:10和01.

代码:

def g(k)
  set_bits_seen = 0
  all_bits_seen = 0
  
  total = 0
  
  while k > 0
    all_bits_seen += 1
    
    if k % 2 == 1 # cur bit is set
      set_bits_seen += 1
      if all_bits_seen > set_bits_seen
        total += n_choose_k(all_bits_seen - 1, set_bits_seen)
      end
    end
    k /= 2
  end
  return total
end

def n_choose_k(n, k)
  return 1 if k == 0 or k == n
  (k + 1 .. n).reduce(:*) / (1 .. n - k).reduce(:*)
end

结果:

1.upto(20) do |i|
  puts "#{i.to_s(2)}  --  #{g(i)}"
end

1  --  0
10  --  1
11  --  0
100  --  2
101  --  1
110  --  2
111  --  0
1000  --  3
1001  --  3
1010  --  4
1011  --  1
1100  --  5
1101  --  2
1110  --  3
1111  --  0
10000  --  4
10001  --  6
10010  --  7
10011  --  4
10100  --  8

举个大例子:

> g(123456789123456789123456789)
=> 3594960708495168399327022

Python相关问答推荐

如何根据另一列值用字典中的值替换列值

更改matplotlib彩色条的字体并勾选标签?

pandas DataFrame GroupBy.diff函数的意外输出

Pystata:从Python并行运行stata实例

Deliveryter Notebook -无法在for循环中更新matplotlib情节(保留之前的情节),也无法使用动画子功能对情节进行动画

Matlab中是否有Python的f-字符串等效物

对某些列的总数进行民意调查,但不单独列出每列

我们可以为Flask模型中的id字段主键设置默认uuid吗

如何在给定的条件下使numpy数组的计算速度最快?

在单个对象中解析多个Python数据帧

SQLAlchemy bindparam在mssql上失败(但在mysql上工作)

ConversationalRetrivalChain引发键错误

替换现有列名中的字符,而不创建新列

如何删除重复的文字翻拍?

递归函数修饰器

应用指定的规则构建数组

从列表中分离数据的最佳方式

如何在Quarto中的标题页之前创建序言页

如何在基于时间的数据帧中添加计算值

Django REST框架+Django Channel->;[Errno 111]连接调用失败(';127.0.0.1';,6379)