TopCoder SRM 643 Div1 Easy: TheKingsFactorization (素因数分解)

解法

 2 \times 素数(>10^8) \times 素数(>10^8)

上のような整数を素因数分解する場合、ヒントを駆使しても10の8乗ループをすることになるが、primes[i] <= N/primes[i+1] <= primes[i+1]ならば、N/primes[i+1]は必ず素数で、primes[i]とprimes[i+1]の間にあるので、ループする必要がなくなる。

コード

import java.util.ArrayList;

public class TheKingsFactorization {

	public long[] getVector(long N, long[] primes) {
		ArrayList<Long> ans = new ArrayList<>();
		for (int i = 0; i < primes.length; i++) {
			N /= primes[i];
			ans.add(primes[i]);

			if (i < primes.length - 1 && primes[i] == primes[i + 1]) {
				// primes[i]=primes[i+1]ならば、その間にある素数もprimes[i]である
				N /= primes[i];
				ans.add(primes[i]);
				continue;
			}

			if (i == primes.length - 1) {
				// 最後の素数で割り終わってもNが1になっていない時、残ったNは必ず素数である
				if (N != 1) {
					ans.add(N);
				}
				break;
			}

			// primes[i]が2の時、Nが2で割れるかどうか
			if (primes[i] == 2) {
				if (N % 2 == 0) {
					N /= 2;
					ans.add(2L);
					continue;
				}
				primes[i]++;
			}

			if (N / primes[i + 1] <= primes[i + 1] && N > primes[i + 1]) {
				// N / primes[i + 1] <= primes[i + 1]ならば、
				// 素数列はprimes[i], N/primes[i+1], primes[i+1]という並びになる
				ans.add((long) N / primes[i + 1]);
				N = primes[i + 1];
				continue;
			}

			for (long j = primes[i]; j <= Math.min(primes[i + 1], Math.min(Math.sqrt(N), N / primes[i + 1])); j += 2) {
				if (N % j == 0) {
					N /= j;
					ans.add(j);
					break;
				}
			}

		}

		long[] ret = new long[ans.size()];
		for (int i = 0; i < ret.length; i++) {
			ret[i] = ans.get(i);
		}

		return ret;
	}
}