HDU 5133 Squared Frequency

題意:
給你一個K 位小數F(0<F<1) ,對於正整數PQ ,如果(PQ)2 四捨五入保留K 位小數後和F相等,則認爲有序對(P,Q) 是合法的,在所有合法的有序對中取Q最小的,如果不唯一,取P最小的。

解法:
Stern–Brocot tree上走就可以了,從12 開始,如果比F大,往左子樹走,如果比F小,往右子樹走。
爲了不損失精度,我把題目轉換爲了整數的運算,由於爆long long了,我寫的大數,寫的姿勢要優美一點,反正我是T了很多發。

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;

char cmp(string a, string b)
{
    if(a.size() < b.size()) return '<';
    if(a.size() > b.size()) return '>';
    for(int i = 0; i < a.size(); i++)
    {
        if(a[i] < b[i]) return '<';
        if(a[i] > b[i]) return '>';
    }
    return '=';
}
string add(string a, string b)
{
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    int len = max(a.size(),b.size());
    while(a.size() < len) a.push_back('0');
    while(b.size() < len) b.push_back('0');

    string c; int tt = 0;
    for(int i = 0; i < len; i++)
    {
        int t = (a[i]-'0') + (b[i]-'0') + tt; tt = 0;
        if(t >= 10) t %= 10, tt = 1;
        c.push_back('0'+t);
    }
    c.push_back('0'+tt);

    while(c.size() > 1 && c[c.size()-1] == '0') c.erase(--c.end());
    reverse(c.begin(), c.end());
    return c;
}
string sub(string a, string b)
{
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    int len = max(a.size(),b.size());
    while(a.size() < len) a.push_back('0');
    while(b.size() < len) b.push_back('0');

    string c; int tt = 0;
    for(int i = 0; i < len; i++)
    {
        int t = a[i] - b[i] - tt; tt = 0;
        if(t < 0) t += 10, tt = 1;
        c.push_back('0'+t);
    }

    while(c.size() > 1 && c[c.size()-1] == '0') c.erase(--c.end());
    reverse(c.begin(), c.end());
    return c;
}
string mul(string a, string b)
{
    string c;
    vector<int> v;
    for(int i = 0; i <= a.size()+b.size(); i++)
        v.push_back(0);
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    for(int i = 0; i < a.size(); i++)
    for(int j = 0; j < b.size(); j++)
    {
        v[i+j] += (a[i]-'0')*(b[j]-'0')%10;
        v[i+j+1] += (a[i]-'0')*(b[j]-'0')/10;
    }
    for(int i = 0; i < v.size(); i++)
    {
        c.push_back(v[i]%10+'0');
        if(i+1 != v.size()) v[i+1] += v[i]/10;
    }
    while(c.size() >= 2 && *c.rbegin() == '0') c.erase(--c.end());
    reverse(c.begin(), c.end());
    return c;
}
string mul2(string a, long long b)
{
    string c;
    reverse(a.begin(), a.end());
    long long t = 0;
    for(int i = 0; i < a.size(); i++)
    {
        t += (a[i] - '0') * b;
        c.push_back(t % 10 + '0');
        t /= 10;
    }
    while(t) c.push_back(t % 10 + '0'), t /= 10;
    reverse(c.begin(), c.end());
    return c;
}
string divide(string a, string b)
{
    string c, mid;
    if(a[0] != '0') a.push_back('0');
    if(a.size() < b.size()) return "0";

    int k = b.size()-1;
    for(int i = 0; i < k; i++)
        mid.push_back(a[i]);

    while(k < a.size())
    {
        mid.push_back(a[k++]);
        while(mid[0] == '0' && mid.size() > 1)
            mid.erase(mid.begin());
        int t = 0;
        while(cmp(mid, b) != '<')
            mid = sub(mid, b), t++;
        c.push_back('0' + t);
    }
    while(c[0] == '0' && c.size() > 1) c.erase(c.begin());

    int last = *c.rbegin() - '0';
    if(c.size() > 1)
        c.erase(--c.end());
    else
        c = "0";
    if(last < 5)
        return c;
    else
        return add(c, "1");
}
string ll2string(long long a)
{
    string c;
    while(a) c.push_back('0'+a%10), a /= 10;
    reverse(c.begin(), c.end());
    return c;
}

string F, Min, Max; int bit;
char check(long long p, long long q)
{
    string p2, q2;
    if(p <= 1e9)
        p2 = ll2string(p*p);
    else
    {
        string s = ll2string(p);
        p2 = mul2(s, p);
    }
    if(p2[0] != '0') p2.insert(p2.end(), bit, '0');

    if(q <= 1e8)
    {
        q2 = ll2string(q*q);
        if(cmp(mul2(Min,q*q), p2) == '>') return '<';
        if(cmp(p2, mul2(Max,q*q)) != '<') return '>';
    }
    else
    {
        string s = ll2string(q);
        q2 = mul2(s, q);
        if(cmp(mul(Min,q2), p2) == '>') return '<';
        if(cmp(p2, mul(Max,q2)) != '<') return '>';
    }

    return '=';
}
void solve()
{
    long long pl = 0, ql = 1, pr = 1, qr = 1, p, q;
    while(true)
    {
        p = pl + pr; q = ql + qr;
        char ch = check(p, q);
        if(ch == '=') break;

        if(ch == '<')
        {
            long long l = 1, r = 1e9/qr;
            while(l < r)
            {
                long long m = (l + r + 1) >> 1;
                ch = check(pl+m*pr, ql+m*qr);
                if(ch == '<')
                    l = m;
                else
                    r = m - 1;
            }
            pl = pl+l*pr; ql = ql+l*qr;
        }
        else
        {
            long long l = 1, r = 1e9/ql;
            while(l < r)
            {
                long long m = (l + r + 1) >> 1;
                ch = check(m*pl+pr, m*ql+qr);
                if(ch == '>')
                    l = m;
                else
                    r = m - 1;
            }
            pr = l*pl+pr; qr = l*ql+qr;
        }
    }

    printf("%lld/%lld\n", p, q);
}

int main()
{
    int ca = 1;
    while(cin >> F)
    {
        F.push_back('0');
        bit = F.size() - 2;
        F.erase(0,2);
        while(*F.begin() == '0') F.erase(F.begin());
        Min = sub(F, "5");
        Max = add(F, "5");

        printf("Case #%d: ", ca++);
        solve();
    }

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章