AOJ1208 Rational Irrationals

問題リンク Rational Irrationals

  • 概要

正の整数p, nが与えられる。ここで、Qnをn以下の正の整数を使って表せる有理数の集合とする。Qnに属するものの中で√pより小さくて最大のものu/vと、√pより大きくて最小のものx/yを答えよ。

  • 解法

1/1から始めていき、√pに近づくように分母と分子を変えていきます。√pより小さければ分子を+1し、そうでなければ分母を+1します。分母と分子が共にn以下の間続け、u/vとx/yを更新していきます。

  • ソース
import java.util.Scanner;

//Rational Irrationals
public class AOJ1208 {

	static long gcd(long a, long b){
		if(a < b){
			long tmp = a;
			a = b;
			b = tmp;
		}
		while(b!=0){
			long r = a%b;
			a = b;
			b = r;
		}
		return a;
	}

	void run(){
		Scanner sc = new Scanner(System.in);
		while(true){
			int p = sc.nextInt();
			int n = sc.nextInt();
			if((p|n)==0)break;
			double rp = Math.sqrt(p);
			int num = 1;
			int den = 1;
			boolean up = true;
			int x, y, u, v;
			x = y = u = v = 0;
			double d1, d2;
			d1 = -n;
			d2 = n;
			while(num<=n&&den<=n){
				double d = num*1.0/den-rp;
				if(d<0){
					up = true;
					if(d1<d&&gcd(num,den)==1){
						d1 = d;
						u = num;
						v = den;
					}
				}
				else{
					up = false;
					if(d<d2&&gcd(num,den)==1){
						d2 = d;
						x = num;
						y = den;
					}
				}
				num += up?1:0;
				den += up?0:1;
			}
			System.out.println(x+"/"+y+" "+u+"/"+v);
		}
	}

	public static void main(String[] args) {
		new AOJ1208().run();
	}
}