由于输入量大,程序耗时太长
Program taking too long for large input
我正在使用一个方程,在这个方程中,我们必须找到给定b的值,x可以取的最大值。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
?
如果对于x = m
,不等式成立,则对于所有整数< m
也成立。如果它对m
不成立,那么它对> m
也不成立。这说明了什么算法?
如果你想宠坏自己,点击这里查看算法
这不仅仅是一个优化问题。(关于优化,请参阅IVlad的答案)。这也是一个正确性问题。对于非常大的值,表达式会导致整数溢出:简单地说,它会从ULLONG_MAX转回零,并且您的循环在没有检测到这一点的情况下继续进行。您需要在代码中构建溢出检测。
一个非常简单的观察可以在O(1)时间内解决你的问题。
查找k = sqrt(sqrt(b))
如果k
满足你的不等式,k
就是你的答案。如果没有,k-1
就是你的答案。
旧答案(这里真正的问题不是迭代次数太多,而是整数溢出;请阅读"更新"部分;我把这部分保留在这里,以记录错误假设的历史):
这些值非常大。当你的程序检查从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;
}
所以,你需要优化这个算法(即减少迭代次数):因为你的函数是单调的,你可以使用二分搜索算法(参见二分法也说明)。
还有一个可能的整数溢出问题:函数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+1 < ULLONG_MAX
,则设置为x
。因此,最初的问题(关于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:答案是关于65535.75...
,所以xmax==65535
。因此,如果我们从0
检查x
到xmax
,我们将不会有溢出问题。这也是我们的初始值的二进制搜索算法。
也意味着,我们不需要在这里使用二进制搜索算法,因为只检查65535个值就足够了。如果x==65535
不是答案,我们必须停止并返回答案65536
。
如果我们需要不硬编码xmax
的跨平台解决方案,我们可以使用任何bigint实现(GMP或任何更简单的解决方案)或实现更精确的乘法等操作。例如:如果我们需要将x
和y
相乘,我们可以计算z=ULLONG_MAX/x
,并将此值与y
进行比较。如果z<y
,我们不能将x
和y
相乘而不溢出
你可以试着找到一个上限,然后从那里开始。
// 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;
不要让x
超过65535
。如果65535
满足不等式,则65536
不满足。
快速回答:
首先,你从x=0开始,然后增加它,这不是最好的解决方案,因为你正在寻找最大值,而不是第一个。所以我要从
这个上界开始x = abs ((b) ^ (1/4))
从该值开始递减,一旦找到元素<=b,就完成了。
你甚至可以这样想:
for y=b to 1
solve(x^4+x^3+x^2+x+1=y)
if has an integer solution then return solution
看到这个
这是一个超级快速的回答,我希望我没有写太多愚蠢的东西,对不起,我还不知道如何在这里写数学
这是一个稍微优化的版本:
#include<iostream>
int main()
{
std::cout << "Sorry, no value of x satisfies the inequality" << std::endl;
return 0;
}
为什么?因为x^4+x^3+x^2+x+1
在x趋于正无穷时是无界的。你的不等式不存在b
。计算机科学是数学的一个子集。
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 更改.cpp程序的输入文件中数据的位置会意外更改输出
- 为什么我的程序在输入某个形状的面积的测量值后没有结束?
- C++外部程序的输入和输出管道
- 为什么在我的程序中输入另一个输入会给我不同的结果
- 如何让我的程序在输入验证的基础上读取素数
- 将两个独立的stdin重定向为程序的输入
- 编写一个程序,输入整数 n 并打印该数字的字符数(符号除外)
- 无法为在 neovim 中运行的程序提供输入
- 为什么当测试用例数为 1 时,我的程序不输入而是打印新行?
- C++击球平均值程序使用输入/输出文件打印名称,平均值,最高/最低平均值时遇到麻烦
- 提供依赖于输入的程序的文件路径
- 词频程序 - 文件输入太大?
- 为什么我的程序在输入main()之前停止工作
- 如何以相反的顺序读取C++程序的输入
- 我需要转换一些代码,以便它适用于输入和输出文件文本
- 将Python脚本的输出链接到C 程序的输入
- C++程序未输入到文件中
- 当我在程序中输入第二个值时,它将我带到第三值,而无法正确执行
- 一个简短的程序,该程序采用输入下部的案例字母,它给出了上案字母的上限字母并在按下Enter键时退出