我正在编写一个我在编码竞赛网站上找到的程序,我有点想办法解决问题但是,我被困在数学部分,我正在完全淡化问题并显示我的内容需要。
首先我需要检查一个数字是否是一个序列的一部分,我的序列是2*a+1
,其中a是序列中的前一个元素,或者2 ^ n-1来获取序列中的第n个项目。所以 1,3,7,15,31,63 ......
我真的不想创建整个序列并检查是否存在数字,但我不确定更快的方法是什么。
第二,如果给我一个数字,可以说25,我想找出我的序列中的下一个最高数字到这个数字。因此,对于25,它将是31,对于47,它将是63,对于8,它将是13.
如何在不创建整个序列的情况下完成这些操作。
我在这里看到了不同序列的类似问题,但我仍然不确定如何解决这个问题
答案 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。
例如,二进制文件中的7
为0000000000000000000000000000111
,二进制文件中的63
为0000000000000000000000000111111
。
此解决方案从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;
}