我正在尝试这个问题,http://www.spoj.pl/problems/TWOSQ/。我们必须找到表示数字(大到10 ^ 15)作为平方和的不同方式的数量(不计算两次,即5 ^ 2 + 1 ^ 2和1 ^ 2 + 5 ^ 2是相同的) 。我以前见过这个任务,这也是我之前解决的问题。我不断得到法官的错误答案。有人可以告诉我为什么吗?或者建议采用不同的方法。我已经根据需要添加了评论以便理解。提前谢谢!。
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
long long X;
cin >> X;
const double EPS = 1e-6;
long long int count = 0;
// add EPS to avoid flooring x.99999 to x
for (int a = 0; a <= sqrt(X/2) + EPS; a++)
{
long long int b2 = X - a*a; // b^2
long long int b = (long long int) (sqrt(b2) + EPS);
if (abs(b - sqrt(b2)) < EPS) // check b is an integer
count++;
}
cout << count << endl;
}
答案 0 :(得分:1)
我可以看到两个问题。
b2
时,使用表达式a*a
。如果a
只是一个int,那么这将很快溢出。 EPS
的价值太大了。你会得到误报。使用最多53个有效位存储双精度浮点数。这意味着可以精确表示大约8e15的所有整数。要使这个数字的平方根正确舍入,你需要大约两倍的精度,这样你就可以得到4e15,仍在你的范围内。
所以,我会做两件事:
EPS
并使用精确比较。它们应该在您指定的范围内正常工作(最多X = 1e15)。答案 1 :(得分:0)
你在主循环中使用EPS存在根本缺陷(可以想象它可以避免任何实际的错误,因为丢番图的原因,但这需要更多的思考而不是保证)。假设X / 2非常接近完美的正方形,例如10 ^ 14-1。然后sqrt(X / 2)将是大约10 ^ 7 - 0.5 * 10 ^ -7,它将使双精度浮点数下溢并舍入到10 ^ 7。
为什么不在2 * a * a&gt;时停止循环? X?当然,修复整数溢出危险。
答案 2 :(得分:0)
我想我知道你要做什么,它很酷......试试这个:
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
typedef unsigned long long int data_type;
int main()
{
data_type value = 0,
count = 0,
index = 0,
max = 0,
b_1 = 0;
cin >> value;
max = (data_type)sqrt(value);
char *flags = new char[max];
memset(flags, 0, max);
for (index = 0; index < max; index++)
{
b_1 = value - (index * index);
if (!((data_type)sqrt(b_1) - sqrt(b_1)) && !flags[(data_type)(sqrt(b_1))] && !flags[index])
{
flags[(data_type)sqrt(b_1)] = 1;
flags[index] = 1;
count++;
}
}
cout << count << endl;
}
据我所知,然后采取差异,通过取平方根并检查任何剩余的浮点值,检查这个差异本身是否是一个完美的正方形,有点酷。
尚未经过全面测试如果有任何错误或问题,我会道歉。
我认为这个问题很重要。
请注意,(10**15)**.5
约为32兆,因此将分配多少
祝你好运。
答案 3 :(得分:0)
我尝试了很多但是因为某种原因仍然得到了错误的答案。因此,我研究了一种不同的方法,并且能够找到这个非常快速的解决方案。
long long L=res=0, R=(long long)sqrt(X) + 1;
while (L<=R)
{
long long Y = L*L + R*R;
if (Y > X) R--;
else if (Y < X) L++;
else res++, L++;
}