1187 寻找分数
给出 a,b,c,d, 找一个分数p/q,使得a/b < p/q < c/d,并且q最小。例如:1/3同1/2之间,符合条件且分母最小的分数是2/5。(如果q相同,输出p最小的)
Input
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000) 第2 - T + 1行:每行4个数,a,b,c,d,中间用空格分隔。(1 <= a,b,c,d <= 10^9)
Output
输出共T行,对应符合条件的分数。
Input示例
4 1 3 1 2 2 1 3 1 2 1 4 1 1000 1001 1001 1002
Output示例
2/5 5/2 3/1 2001/2003
一开始想到二分q,因为q越大显然选择越多(其实是错的)
有了q之后设p=1
可以用lcm把三个式子的分母通分,得到分子
然后可以找在新的分子中存不存在a<p<c
写完后发现过不了样例
然后发现有极少极少的数不满足单调性,大部分都是满足的
但是这样就不能二分了
怎么办??
我直接枚举,非常暴力。
我想着应该会超时
我一交上去
我靠25个点过了22个点
3个点没过是因为WA,最后一个点900多毫秒,卡过去了
其实考试这样的话我就满意了
然后我觉得没过是因为取lcm的时候会爆long long
我就改成了unsigned long long
多过了一个点。
写高精度??
不行,这样就会超时。
所以这就是我这种做法的极限了,25个点能过23个点
#include<bits/stdc++.h> #define REP(i, a, b) for(register int i = (a); i < (b); i++) #define _for(i, a, b) for(register int i = (a); i <= (b); i++) using namespace std; typedef unsigned long long ull; ull a, b, c, d; ull ansp, ansq; ull gcd(ull a, ull b) { return !b ? a : gcd(b, a % b); } ull lcm(ull a, ull b) { return a / gcd(a, b) * b; } bool check(ull q) { ull t = lcm(lcm(b, q), d); ull p = t / q, ta = t / b * a, tc = t / d * c; t = ta / p + 1; if(ta < t * p && t * p < tc) { ansp = t; ansq = q; return true; } return false; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%llu%llu%llu%llu", &a, &b, &c, &d); ull t = gcd(a, b); a /= t; b /= t; t = gcd(c, d); c /= t; d /= t; for(register ull ans = 1; ; ans++) if(check(ans)) { printf("%llu/%llu\n", ansp, ansq); break; } } return 0; }
我们来讲一下正解
待补……