题意:
给你一个
K
位小数
解法:
在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;
}