AOJ1069 Squid Multiplication

問題リンク Squid Multiplication

  • 解法

a0を頑張って特定します。a0が決まると、数列Bの中の偶数のものをa0で割ることで数列Aの奇数が作り出せます。
数列Bの2つの偶数のものbi, bjは
bi = a0 * ai
bj = a0 * aj
となっています。また、Bの中の奇数の中にはai*ajとなっているbkがあるはずです。
bk = ai * aj
これらから、
bi * bj / bk = a0^2
という式が導けます。
よって、適当な奇数を1つ選んでbkとし、biとbjの組み合わせを全て選んでa0を作り、このa0から数列Bを復元できるかを調べれば解けます。
偶数の項は必ずN個だけあるので、調べる組み合わせはN*(N-1)/2個です。
bi*bj/bkを計算するときに、そのまま掛け算するとlongでもオーバーフローするのでgcdをとって項を小さくする必要があります。biとbjが正しい組み合わせなら演算結果がオーバーフローすることはないので解となるa0が正しく求まります。

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

//Squid Multiplication
public class AOJ1069 {

	long gcd(long a, long b){
		return b==0?a:gcd(b, a%b);
	}

	void run(){
		Scanner sc = new Scanner(System.in);
		for(;;){
			int n = sc.nextInt();
			if(n==0)break;
			List<Long> even = new ArrayList<Long>(), odd = new ArrayList<Long>(), list = new ArrayList<Long>();
			for(int i=0;i<n*(n+1)/2;i++){
				long x = sc.nextLong();
				list.add(x);
				if(x%2==0)even.add(x);
				else odd.add(x);
			}
			Collections.sort(list);
			boolean con = true;
			for(int i=0;i<even.size()&&con;i++)for(int j=i+1;j<even.size()&&con;j++){
				long bi = even.get(i), bj = even.get(j), bk = odd.get(0);
				long g = gcd(bi, bk);
				bi/=g; bk/=g;
				g = gcd(bj, bk);
				bj/=g; bk/=g;
				double r = Math.sqrt(bi*bj/bk);
				long a0 = (long)r;
				if(a0==0)continue;
				long[] a = new long[n];
				boolean f = true;
				List<Long> l = new ArrayList<Long>();
				for(int x=0;x<n;x++){
					long y = even.get(x);
					if(y%a0!=0){
						f = false; break;
					}
					a[x]=even.get(x)/a0;
					l.add(a0*a[x]);
				}
				if(!f)continue;
				for(int x=0;x<n;x++)for(int y=x+1;y<n;y++)l.add(a[x]*a[y]);
				Collections.sort(l);
				boolean ok = true;
				for(int x=0;x<l.size();x++){
					long A = l.get(x), B = list.get(x);
					if(A!=B){
						ok = false; break;
					}
				}
				if(ok){
					Arrays.sort(a);
					System.out.println(a0);
					con = false;
					for(int x=0;x<n;x++)System.out.print(a[x]+(x==n-1?"\n":" "));
				}
			}
		}

	}

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