■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 件のコメント:
コメントを投稿