繁体   English   中英

将1到N的所有数字相加,并将设置的位数设置为2

[英]Adding all numbers from 1 to N which have number of set bits as 2

我有一个问题,我必须添加从1到N的数字,它们的设置位为2。像N = 5一样,我们应该得到值8,因为数字3和5的2位设置为1。 我在Java中实现相同。 我得到了正确的int值的o / p值,但是当涉及到长值时,这会花费很多时间或冻结,而当我在代码判断站点上提交该值时,则会给出运行时间超出消息。 请指导我如何优化代码以更快地运行它,谢谢:)

public static void main(String[] args)
{
    long n = 1000000L;
    long sum = 0;
    long start = System.currentTimeMillis();
    for(long i = 1L ; i <= n ; i++)
    {
        if(Long.bitCount(i) == 2)
        {
            sum += i;
        }
    }
    long end = System.currentTimeMillis();
    System.out.println(sum);
    System.out.println("time="+(end-start));
}

正如@hbejgel指出的那样,循环遍历所有数字并检查其位数是没有意义的。 您可以简单地用2位构造数字并将其相加。

您可以通过在long中选择两个不同的位位置来构造一个2位数字,即“较高”位和“较低”位”:

long i = (1 << higher) + (1 << lower);

因此,您可以简单地循环所有这些数字,直到构造的值超出限制为止:

long sum = 0;
outer: for (int higher = 1; higher < 63; ++higher) {
  for (int lower = 0; lower < higher; ++lower) {
    long i = (1 << higher) + (1 << lower);
    if (i <= n) {
      sum += i;
    }
    if (i >= n) break outer;
  }
}

假设我们知道最接近的数x等于或小于N,带有2个置位,那么我们可以使用幂级数公式快速求和两个置位的所有位置,例如,如果x = b11000 ,我们和

  4*2^0 + S(4)
+ 3*2^1 + S(4) - S(1)
+ 2*2^2 + S(4) - S(2)
+ x

where S(n) = 2 * (1 - 2^n) / (1 - 2) 
           = 2 + 2^2 + 2^3 ... + 2^n

使用5中的2编码的数字时,每个一位数字中恰好设置了两位。 的总和是45,与外N×(N-1)/2为0≤ N <9。

我认为这个问题应该可以找到模式。

  1. 快进。 给定数字N,您可以知道应该从设置的前两位开始按位掩码计数最大的数字。 所以你有一个较小的M

  2. 跳到下一个计数的数字给定设置了两位的任何数字,下一个最大数字是将第二个位移位一位,直到下溢。

  3. 跳到下一个顺序当第2组发生下溢时,将最高位移1,也将其右移。

您实际上并不需要在N上循环,但需要循环。

下一个问题:您能回答很多吗? N> 100,000,000

下一个下一个问题:当X> 2时,您能否针对X位回答相同的问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM