检查序列中存在的数字

时间:2013-03-02 05:08:04

标签: java algorithm math sequence

我正在编写一个我在编码竞赛网站上找到的程序,我有点想办法解决问题但是,我被困在数学部分,我正在完全淡化问题并显示我的内容需要。

首先我需要检查一个数字是否是一个序列的一部分,我的序列是2*a+1,其中a是序列中的前一个元素,或者2 ^ n-1来获取序列中的第n个项目。所以 1,3,7,15,31,63 ......

我真的不想创建整个序列并检查是否存在数字,但我不确定更快的方法是什么。

第二,如果给我一个数字,可以说25,我想找出我的序列中的下一个最高数字到这个数字。因此,对于25,它将是31,对于47,它将是63,对于8,它将是13.

如何在不创建整个序列的情况下完成这些操作。

我在这里看到了不同序列的类似问题,但我仍然不确定如何解决这个问题

3 个答案:

答案 0 :(得分:2)

首先找到序列中任何术语的显式公式。我懒得写出证明,所以只需在序列中的每个词中加1

 1 + 1 =  2
 3 + 1 =  4
 7 + 1 =  8
15 + 1 = 16
31 + 1 = 32
63 + 1 = 64
...

您可以清楚地看到a_n = 2^n - 1

要检查序列中是否有特定数字,请假设它是:

x = 2^n - 1
x + 1 = 2^n

来自维基百科:

  

整数的二进制表示使得可以应用a   非常快速的测试,以确定给定的正整数x是否为a   力量二:

     
    

正x是2⇔(x&(x - 1))的幂等于零。

  

所以要检查,只需:

bool in_sequence(int n) {
    return ((n + 1) & n) == 0;
}

答案 1 :(得分:1)

由于@Blender已经指出你的序列本质上是2^n - 1,如果使用整数格式来存储它,你可以使用这个技巧:

boolean inSequence(int value) {
    for (int i = 0x7FFF; i != 0; i >>>= 1) {
        if (value == i) {
            return true;
        }
    }
    return false;
}

请注意,对于序列中的每个元素,其二进制表示将是大量0 s,然后是大量1 s。

例如,二进制文件中的70000000000000000000000000000111,二进制文件中的630000000000000000000000000111111

此解决方案从01111111111111111111111111111111开始,使用无符号bitshift,然后比较它是否等于您的值。

美好而简单。

答案 2 :(得分:0)

如何找到下一个更高的数字:

例如,我们得到19(10011),应该返回31(11111)

int findNext(int n){
    if(n == 0) return 1;

    int ret = 2;         // start from 10
    while( (n>>1) > 0){  // end with 100000
        ret<<1;
    }
    return ret-1;
}