■1208 Rational Irrationals
全探索を行うと,O(n2)でかなりキツイ.そこで二部探索を使う.具体的には,分数をm/dとした時,dを1~nまで回し,√pに近くなるようなmを求める.
探索の幅として[1,n]を設定し,m/d<√pを条件とすれば,
m/d<√p<(m+1)/d
もしくは,
m/d<(m+1)/d<√p (ただし,m+1>n)
となる.
事実上計算量はO(n).
import java.util.*; import java.lang.*; import java.math.*; import java.io.*; import static java.lang.Math.*; import static java.util.Arrays.*; public class Main{ Scanner sc=new Scanner(System.in); int INF=1<<28; double EPS=1e-9; int p, m; void run(){ for(;;){ p=sc.nextInt(); m=sc.nextInt(); if((p|m)==0){ break; } solve(); } } void solve(){ long n1=0, d1=1; long n2=m, d2=1; for(long d=1; d<=m; d++){ double left=1, right=m; for(int i=0; i<100; i++){ double mid=(left+right)/2; if(mid*mid<p*d*d+EPS){ left=mid; }else{ right=mid; } } int n=(int)(left+EPS); if(n1*d<n*d1&&n*n<p*d*d){ n1=n; d1=d; } if(++n<=m){ if(p*d*d<n*n&&n*d2<n2*d){ n2=n; d2=d; } } } long gcd=gcd(n1, d1); n1/=gcd; d1/=gcd; gcd=gcd(n2, d2); n2/=gcd; d2/=gcd; println(n2+"/"+d2+" "+n1+"/"+d1); } long gcd(long m, long n){ for(; n!=0;){ m=m%n; long t=m; m=n; n=t; } return m; } void debug(Object... os){ System.err.println(Arrays.deepToString(os)); } void print(String s){ System.out.print(s); } void println(String s){ System.out.println(s); } public static void main(String[] args){ // System.setOut(new PrintStream(new BufferedOutputStream(System.out))); new Main().run(); } }
0 件のコメント:
コメントを投稿