昨天打codeforces,碰到两个bug,在此总结。
用一元二次方程求解公式的精度问题
1、在这里用一元二次方程求解公式之后,由于数据较大极有可能造成精度不高导致转化int类型之后与实际结果差1或着差2。
如公式x*x+x-c>=0,求出满足公式的最小整数x。
这里用一元二次方程求解,由于精度的问题,导致无法得到正确结果。此时将公式转化一下 x*x+x > =c,
假设x*x+x =c,
则 x < sqrt(x*x+x) < x+1
即有x < sqrt(c) < x+1。
所以求出sqrt(c)的上界i,并逐渐递减判断是否i*i+i>=c,是就继续递减,否则得出结果。
无法整除的乘除法运算不能调换
a/b*x 与a*x/b看似这两个步骤得出的结果一样,其实不然。
举个例子,a = 3,b=2, x = 2
式一得出结果 2,式二得出结果3
这也是在写codeforces的拓展欧几里德算法找了一两个小时找到的bug。。
如下:
错误写法:y-=a*x/b;
long long gcd(long long a, long b, long long &x, long long & y) {
if (!b) {
x = 1;
y = 0;
return a;
}
long long g = gcd (b, a%b, y, x);
y -= a*x/b;
return g;
}
正确写法:y-=a/b*x;
long long gcd(long long a, long b, long long &x, long long & y) {
if (!b) {
x = 1;
y = 0;
return a;
}
long long g = gcd (b, a%b, y, x);
y -= a/b*x;
return g;
}
关于对拓展欧几里德算法的推导,见我以前的文章: