AOJ2030 Ruins
問題リンク Ruins
- 概要
2つの正整数A, Bが与えられる。ここで、a1*a2=A, b1*b2=Bとなるような正整数a1, a2, b1, b2を考える。このとき、a1, a2, b1, b2を昇順にソートし、隣り合った数の差の2乗の総和Sの最小値を求めよ。
1 <= A, B <= 10000
- 解法
1〜10000の約数をそれぞれ最初に列挙しておきます(√nまで回せば十分です)。
あとは、A, Bそれぞれの約数を全通り試して最小値を取ります。一番約数の数が大きいもので32個しかないので時間は全く問題ありません。
- ソース
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Scanner; //Ruins public class AOJ2030 { @SuppressWarnings("unchecked") void run(){ Scanner sc = new Scanner(System.in); List<Integer>[] l = new List[10001]; for(int i=1;i<=10000;i++)l[i] = new ArrayList<Integer>(); for(int i=1;i<=10000;i++)for(int j=1;j*j<=i;j++){ if(i%j==0)l[i].add(j); } for(;;){ int a = sc.nextInt(), b = sc.nextInt(); if((a|b)==0)break; int min = 1<<29; int[] t = new int[4]; for(int p:l[a])for(int q:l[b]){ t[0]=p; t[1]=a/p; t[2]=q; t[3]=b/q; Arrays.sort(t); min = Math.min(min, (t[1]-t[0])*(t[1]-t[0])+(t[2]-t[1])*(t[2]-t[1])+(t[3]-t[2])*(t[3]-t[2])); } System.out.println(min); } } public static void main(String[] args) { new AOJ2030().run(); } }