Q1(hdu6209):
给出常数k,欲用类似二分搜索的迭代策略,求解方程k^2=x^3分母不超过100000的最近似的解的最简分数形式。
分析:这是一个很直观方程求数值解的数值分析问题,因此应该能够联想到的是用迭代搜索策略。这里有如下两种策略:
策略1(二分迭代):可行解在[a/b , c/d]中,下次迭代考虑重点(ad+bc)/2cd.
策略2(类二分策略):可行解在[a/b , c/d]中,下次迭代考虑(a+c)/(b+d).
考虑这里用策略而能够保证整个迭代过程中,分数的分子和分母一定是互素的,这也会为迭代的效率上带来优化。参考代码如下:
#include<cstdio> using namespace std; typedef long long LL; typedef long double LD; const LD INF = 1e60; LD Abs(LD x){ return x > 0 ? x : -x; } int main(){ int T; LL L_son , L_mom ,R_son , R_mom , M_son , M_mom , ans_son , ans_mom; LD deta; LL K , x , aim; scanf("%d" , &T); while(T--){ scanf("%lld" , &K); aim = K * K; x = 1; while(x*x*x < aim) x++; if(x*x*x == aim){ printf("%lld/1 " , x); continue; } else{ //分布在[x-1 , x]之中,x - 1是解的整数部分 L_son = x - 1; L_mom = 1; R_son = x; R_mom = 1; } deta = INF; while(1){ M_son = L_son + R_son; M_mom = L_mom + R_mom; if(M_mom > 100000) break; LD u = M_son; LD v = M_mom; LD temp = u*u*u/v/v/v; if(Abs(temp - aim) < deta){//维护最小距离 ans_son = M_son; ans_mom = M_mom; deta = Abs(temp - aim); } if(temp < aim){ //削减迭代区间 L_son = M_son; L_mom = M_mom; } else{ R_son = M_son; R_mom = M_mom; } } printf("%lld/%lld " , ans_son , ans_mom); } return 0; }