HDU 6209 数学

来源:互联网 发布:北京快道网络 董事长 编辑:程序博客网 时间:2024/06/06 15:48

简略题意:问分母在1e5范围内的最简分数中,距离y=k/xy=(x)的在第一象限的交点的x坐标最近的分数是什么。

k/x=(x) => x=k2/3
我们可以先暴力找到最接近k的整数部分,如果直接找到了答案就输出即可。
否则答案即在x11x1之间,这部分的复杂度是O(k2/3)的。

然后考虑如何在这段区间找数。
给出闭区间[l,r],二分找一个数挺显然的,不过为了使得我们二分出的分数是最简分数,我们可以参考法里数列的构造法。
对于[luld,rurd],每次取二分中点[lu+ruld+rd]即可保证每次为最简分数。
关于法里数列可以看这里。

#define others#ifdef poj#include <iostream>#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <vector>#include <string>#endif // poj#ifdef others#include <bits/stdc++.h>#endif // others//#define file#define all(x) x.begin(), x.end()using namespace std;const long double eps = 1e-8;//int dcmp(long double x) { if(_abs(x)<=eps) return 0; return (x>0)?1:-1;};typedef long long LL;long double _abs(long double x) {    return x<0?-x:x;}namespace solver {    int t;    LL k;    void solve() {        scanf("%d", &t);        LL a1,a2, b1, b2, m1, m2, A, B;        while(t--) {            scanf("%lld", &k);            LL x = 0;            while(x*x*x<k*k) x++;            if(x*x*x==k*k) printf("%lld/1\n", x);            else {                long double tt = k * k;                LL au = x-1, bu = x;                LL ad = 1, bd = 1;                long double minv = 1e60;                for(;;) {                    LL mu = au + bu, md = ad + bd;                    if(md > 100000) break;                    long double u = mu, v = md;                    long double val = u*u*u/v/v/v;                    if(_abs(val-tt) < minv) {                        minv = _abs(val-tt);                        A = mu, B = md;                    }                    if(val > tt) bu = mu, bd = md;                    else au = mu, ad = md;                }                printf("%lld/%lld\n", A, B);            }        }    }}int main() {    solver::solve();    return 0;}
原创粉丝点击