AOJ1232 Calling Extraterrestrial Intelligence Again

問題リンク Calling Extraterrestrial Intelligence Again

  • 概要

m, a, bの3つの値が与えられる。
2つの素数の組p, qを
p*q<=m
a/b <= p/q <= 1
を満たすものとするとき、p*qを最大にするようなp, qを答えよ
4 < m < 10^5
1 <= a <= b <= 1

  • 解法

エラトステネスの篩で10^5までの素数を求めておきます。
p*qの積Xを固定し、素因数を1つ見つけpとします。
qをX/pとし、このqも素数であり、a/b<=p/q<=1を満たすのならば、このpとqが答えです。
a/b<=p/q<=1の判定にa/bの値とp/qの値を使うのはあまり嬉しくないので、式変形して
p<=q
a*q<=b*p
の2つを満たしているかで判定した方がいいと思います。これなら浮動小数点が現れず、整数計算だけで判定できます。

  • ソース
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

//Calling Extraterrestrial Intelligence Again
public class AOJ1232 {

	void run(){
		Scanner sc = new Scanner(System.in);
		int N = 100000;
		boolean[] f = new boolean[N+1];
		Arrays.fill(f, true);
		List<Integer> sieve = new ArrayList<Integer>();
		f[0]=f[1]=false;
		for(int i=2;i<=N;i++)if(f[i]){
			sieve.add(i);
			for(int j=i+i;j<=N;j+=i)f[j]=false;
		}
		int n = sieve.size();
		for(;;){
			int m = sc.nextInt(), a = sc.nextInt(), b = sc.nextInt();
			if((m|a|b)==0)break;
			boolean con = true;
			for(int x=m;x>0;x--){
				if(!con)break;
				for(int ip=0;ip<n;ip++){
					int p = sieve.get(ip);
					if(p*p>x)break;
					int q = x/p;
					if(x%p!=0||p*b<q*a)continue;
					if(f[q]){
						con = false;
						System.out.println(p+" "+q);
						break;
					}
				}
			}
		}
	}
	
	public static void main(String[] args) {
		new AOJ1232().run();
	}
}