SRM 246 DIV1 Hard CalcRoot
問題
abs(sqrt(N) - a/b)が最小となる正整数a, b (b <= D)を求めよ
- 1 <= N <= 1000000
- 1 <= D <= 1000
解答
long doubleでやるだけ。
最小との比較は整数演算だけでもできるらしい(Editorial参照)
コメント
簡単回。
最小との比較の誤差を何も気にせずに書いてた。それ駄目だろ!まあlong doubleでよかったけど
コード
#include <string> #include <sstream> #include <cmath> #define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i)) #define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i)) using namespace std; typedef long double ld; template<typename T>T gcd_positive(T x, T y) { return y == 0 ? x : gcd_positive(y,x%y); } struct CalcRoot { string approximate(int N, int D) { ld s = sqrt(N*1.L); ld me = 1e99; int mn, md; rer(d, 1, D) rep(i, 3) { int n = (int)(s * d + (i * 0.5)); ld e = abs(n * 1.L / d - s); if(e < me) mn = n, md = d, me = e; } int g = gcd_positive(mn, md); mn /= g; md /= g; stringstream ss; ss << mn << "/" << md; return ss.str(); } };