我使用的公式中我们必须找到 x 在给定 b 的值时可以采用的最大值。 x 和 b 都只能采用非负整数值。等式是:
x^4+x^3+x^2+x+1≤b
我已经编写了以下代码(显然是愚蠢的)来解决它:
#include<iostream>
#include<climits>
using namespace std;
int main()
{
unsigned long long b,x=0;
cout<<"hey bro, value of b:";
cin>>b;
while(x++<b)
if(x*x*x*x+x*x*x+x*x+x+1>b)
break;
if(b==0)
cout<<"Sorry,no value of x satisfies the inequality"<<endl;
else
cout<<"max value of x:"<<x-1<<endl;
return 0;
}
上述代码在b=LONG_MAX
之前可以正常工作,但在b=LONG_LONG_MAX
或b=ULLONG_MAX
之后,它会一直开始。如何才能解决此问题,使其最适合 b=ULLONG_MAX
?
答案 0 :(得分:4)
如果对于x = m
,不等式成立,那么它也适用于所有整数< m
。如果它不适用于m
,则它不会保留任何整数> m
。这表明了什么算法?
如果您想破坏自己,请点击here查看算法。
答案 1 :(得分:3)
这不仅仅是一个优化问题。 (有关优化,请参阅IVlad的答案)。这也是一个正确性问题。对于非常大的值,表达式会导致整数溢出:简单地说,它从ULLONG_MAX回绕到零,并且你的循环继续没有检测到这一点。您需要在代码中构建溢出检测。
答案 2 :(得分:2)
旧答案(这里的实际问题不是迭代次数多,而是整数溢出;请从“更新”部分阅读;我将此部分保留在这里以了解错误假设的历史):
这些值非常大。当您的程序检查从0到LONG_LONG_MAX
的每个值时,它会对9*10^12
个操作进行调整,不是吗?对于ULLONG_MAX
,我们有18*10^12
次操作。尝试修改此程序以查看实际处理速度:
while (x++ < b)
{
if (x % 1000000 == 0)
cout << " current x: " << x << endl;
if (x*x*x*x+x*x*x+x*x+x+1>b)
break;
}
因此,您需要优化此算法(即减少迭代次数):由于您的函数为monotonic,因此您可以使用Binary search algorithm(请参阅Bisection method以获得说明)。< / p>
整数溢出也可能存在问题:对于大值x*x*x*x
,函数x
计算错误。想象一下你的类型是unsigned char
(1个字节)。例如,当您的程序计算250*250*250*250
时,您期望3906250000,但实际上您有3906250000 % 256
(即16
)。因此,如果x
太大,则有可能您的函数将返回值< b
(这将是奇怪的;理论上它可以制动您的优化算法)。好消息是,如果每次检查都正确,你就不会看到这个问题。但是对于更复杂的函数,您还需要支持长数学(例如,使用GMP或其他实现)。
更新:如何避免溢出风险?
我们需要找到x
的最大允许值(让我们称之为xmax
)。如果x
,则允许值x*x*x*x+x*x*x+x*x+x+1 < ULLONG_MAX
。因此,对初始问题(约x*x*x*x+x*x*x+x*x+x+1 < b
)的答案不大于xmax
。让我们找到xmax
(只需在任何系统中求解等式x*x*x*x+x*x*x+x*x+x+1=ULLONG_MAX
,例如WolframAlpha:anwer约为65535.75...
,所以xmax==65535
。所以,如果我们检查{ {1}}从x
到0
我们不会出现溢出问题。它也是二进制搜索算法的初始值。
这也意味着,我们不需要在这里使用二进制搜索算法,因为它只需要检查65535个值。如果xmax
没有回答,我们必须停止并返回回答x==65535
。
如果我们需要跨平台解决方案而不需要65536
的硬编码,我们可以使用任何bigint实现(GMP或任何更简单的解决方案)或实现更准确的乘法和其他操作。示例:如果我们需要多层xmax
和x
,我们可以计算y
并将此值与z=ULLONG_MAX/x
进行比较。如果y
,我们无法将z<y
和x
相乘,而不会溢出。
答案 3 :(得分:2)
一个非常简单的观察在O(1)时间内解决了你的问题。
查找k = sqrt(sqrt(b))
如果k
满足您的不平等,k
就是您的答案。如果没有,k-1
就是您的答案。
答案 4 :(得分:1)
您可以尝试找到一个上限并从那里开始工作。
// Find the position of the most significant bit.
int topBitPosition = 0;
while(b >> topBitPosition)
topBitPosition++;
// Find a rough estimate of b ^ 1/4
unsigned long long x = b >> (topBitPosition - topBitPosition/4);
// Work down from there
while(x*x*x*x+x*x*x+x*x+x+1 > b)
x--;
cout<<"max value of x:"<<x-1<<endl;
答案 5 :(得分:1)
不要让x
超过65535
。如果65535
满足不等式,65536
则不会。
答案 6 :(得分:0)
快速回答:
首先,你从x = 0开始然后增加它,这不是最佳解决方案,因为你正在寻找最大值而不是第一个。 因此,我会从一个可以
的上限出发X = ABS((B)^(1/4))
比从该值减少,并且一旦找到元素&lt; = b,就完成了。
你甚至可以这样思考:
for y=b to 1
solve(x^4+x^3+x^2+x+1=y)
if has an integer solution then return solution
请参阅this
这是一个超级快速的答案我希望我没有写太多愚蠢的事情,对不起我还不知道如何在这里写数学。
答案 7 :(得分:-1)
这是一个稍微优化的版本:
#include<iostream>
int main()
{
std::cout << "Sorry, no value of x satisfies the inequality" << std::endl;
return 0;
}
为什么呢?因为x接近正无穷大,所以x^4+x^3+x^2+x+1
是无界的。你的不平等没有b
。计算机科学是数学的一个子集。