C++ 位的总和是给定的,用于查找塔尔数
问题陈述:将给您一个数字N,您必须判断是否存在一个数字K,以便从1到K的所有数字中的位总和等于N。如果存在,则打印该数字,否则打印“不存在”。不带引号 问题链接: 我的代码复杂度是C++ 位的总和是给定的,用于查找塔尔数,c++,algorithm,big-o,C++,Algorithm,Big O,问题陈述:将给您一个数字N,您必须判断是否存在一个数字K,以便从1到K的所有数字中的位总和等于N。如果存在,则打印该数字,否则打印“不存在”。不带引号 问题链接: 我的代码复杂度是O((logn)^2),人们建议我可以在O(logn)中完成,但我无法理解。 有人能帮我在logn中怎么做吗 下面是我的代码和一些预计算+log(n)^2这就是我所做的 提示 你几乎已经在那里了,考虑一下你的总计函数: LL Total_Bits(LL n) { if(n==0) return 0;
O((logn)^2)
,人们建议我可以在O(logn)
中完成,但我无法理解。
有人能帮我在logn
中怎么做吗
下面是我的代码和一些预计算+log(n)^2
这就是我所做的
提示
你几乎已经在那里了,考虑一下你的总计函数:
LL Total_Bits(LL n)
{
if(n==0) return 0;
LL m = Lmb(n);
n = n - pow(2,m);
return (n+1) + Total_Bits(n) + m*pow(2,(m-1));
}
您需要做的是将此函数转换为一个函数,在给定目标位数的单个调用中计算出n位(从最高有效到最低有效)。这允许您从使用二分法中删除logn因子
你怎么算出n的位呢?好吧,假设我们正在努力计算,在位置m是否需要1。你可以从你的代码中看到,如果n>=2**m,那么答案至少是m*pow(2,(m-1)+1,如果n这里是我在O((logn)^2)中的解。您所做的预计算是不必要的,而且是昂贵的。要检查如何给定一个数字K,从1到K的数字中获取1的数量,请检查此项。知道了这一点,剩下的是一个简单的二进制搜索。我的解决方案:
#包括
使用名称空间std;
typedef无符号长ui64;
ui64系列(ui64 n){
ui64 ans=0;
int x=0;
对于(int i=\u lg(n);i>=0;--i)
如果(n&1LLU 1)*i+1+(1LLU=n)u=m;
否则l=m+1;
}
如果(一(l)==n)printf(“%llu\n”,l);
else printf(“不存在。\n”);
}
}
当你说O(log n ^ 2)时,你是指O((log n)^ 2)还是O(log(n ^ 2))?因为O(log(n ^ 2))=O(2 log n)=O(log n)。@ Sh希奇抱歉它的O((log n)^ 2)@ C++。^2
?(我之所以这样问,是因为我认为它是O(log(n)^3)
)取决于您可能找到的编译器(我使用的是二进制搜索,因为二进制搜索在O(log n)中运行,它将调用函数Total_Bits O(log n)乘以总位的复杂度是log n,二进制搜索在log n中,而总复杂度是O((log n)^2),如果我错了,请纠正我。谢谢你@Peter de Rivaz的这个好主意。
def find_index(N):
"""Compute the index K such that sum of all bits in numbers 1..K is N"""
prefix = 0 # Number of 1's in the answer
answer = 0 # Lower bound on index K
for m in xrange(63,-1,-1):
a = 1 << m
extra = a*prefix + (m*(1<<m)>>1) # Amount we would add to our count if bit m is set
if N>extra:
N -= extra
prefix += 1
answer += a
N-=prefix
return answer if N==0 else "Does Not Exist."
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ui64;
ui64 ones(ui64 n){
ui64 ans = 0;
int x = 0;
for(int i = __lg(n); i >= 0; --i)
if(n & 1LLU << i)
ans += ((1LLU << i) >> 1) * i + 1 + (1LLU << i) * x++;
return ans;
}
int main(){
int t;
ui64 n, l, u, m;
scanf("%d",&t);
while(t--){
scanf("%llu",&n);
l = 0; u = n + 1;
while(l != u){
m = l + (u - l) / 2;
if(ones(m) >= n) u = m;
else l = m + 1;
}
if(ones(l) == n) printf("%llu\n",l);
else printf("Does Not Exist.\n");
}
}