URAL 1948 H - The Robot on the Line 二分 + 数学

时间:2023-03-09 16:14:55
URAL 1948   H - The Robot on the Line 二分 + 数学

http://acm.hust.edu.cn/vjudge/contest/126149#problem/H

给定一条二次函数 f (x) = a * x * x + b * x + c

求一个最小的k,使得f(x) + f(x + 1) + f(x + 2) ..... + f(x + k - 1) 不等于 0 恒成立。

首先把参数统一写成 x + t这样的形式,然后带入去

化简有:a*x*x + (2*a*t+b)*x + a*t*t+b*t+c //现在的t是从0--k-1

列出k个式子,求和(简单的数列求和)。然后就得到一条关于x的二次函数,用判别式判断即可。

为什么能二分?

因为单调。化简后可以看到B*B - 4*A*C。k越大,<0就越成立。因为4*A*C有k的项且指数都比较高。所以这个判断是单调的。

则二分即可。

数字很大 啊。用double居然没爆。应该用到了1e100。double犀利啊

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
LL a, b, c;
bool check (LL t) {
double k = (double)t;
double B = (b + * a * (k - ) + b) * k / 2.0;
double C = a * (k - ) * (k) * ( * (k - ) + ) / + (k - ) * k / * b + k * c;
double A = k * a;
// cout << B << " " << C << " " << A << endl;
return B * B < * A * C;
}
void work () {
cin >> a >> b >> c;
// cout << a << " " << b << " " << c << endl;
LL begin = ;
LL end = 1e18;
// cout << check (9) << endl;
while (begin <= end) {
LL mid = (begin + end) >> ;
// cout << mid << endl;
if (check (mid)) { //mid是满足条件的,就是方程无解的
// cout << " ***" << endl;
end = mid - ;
} else {
begin = mid + ;
}
}
if (begin > 1e18) {
printf ("Infinity\n");
} else {
cout << begin << endl;
}
return ;
} int main () {
#ifdef local
freopen("data.txt","r",stdin);
#endif
int t;
cin >> t;
while (t--) work ();
return ;
}