Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Problem F:
RabbitLunch

うさぎは昼食ににんじんとキウイを1 個ずつ食べる. うさぎはとても個性的なので, 食べるにんじんの種類もキウイの種類も同じであるような, 異なる2 匹のうさぎが存在してはならない.

にんじんは $M$ 種類ある. $i$ 種類目のにんじんは $m_i$ 個ある. キウイは $N$ 種類ある. $i$ 種類目のキウイは $n_i$ 個ある. 最大何匹のうさぎが昼食をとれるか求めよ.

$m_i$ と $n_i$ は次の漸化式を用いて生成せよ.

$m_0 = m0$

$m_{i+1} = (m_i * 58 + md )$ mod $(N + 1)$

$n_0 = n0$

$n_{i+1} = (n_i * 58 + nd )$ mod $(M + 1)$

Constraints

$M$ will be between 1 and 2,500,000, inclusive.

$N$ will be between 1 and 2,500,000, inclusive.

$m0$ and $md$ will be between 0 and $N$, inclusive.

$n0$ and $nd$ will be between 0 and $M$, inclusive.

Input

入力は以下の形式で与えられる:

$M$ $N$ $m0$ $md$ $n0$ $nd$

Output

昼食をとれるうさぎの匹数の最大値を表す整数を 1 行に出力せよ.

Sample Input 1

2 3 1 3 1 0

Sample Output 1

2

Sample Input 2

5 8 1 2 3 4

Sample Output 2

19

Solution in JAVA (judge verdict: Accepted)

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

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

	void run() {
		solver();
	}

	void solver() {
		Scanner sc = new Scanner(System.in);
		int M = sc.nextInt();
		int N = sc.nextInt();
		int m0 = sc.nextInt();
		int md = sc.nextInt();
		int n0 = sc.nextInt();
		int nd = sc.nextInt();
		int[] m = new int[M];
		int[] n = new int[N];
		m[0] = m0;
		n[0] = n0;

		for (int i = 1; i < M; ++i) {
			m[i] = (m[i - 1] * 58 + md) % (N + 1);
		}
		for (int i = 1; i < N; ++i) {
			n[i] = (n[i - 1] * 58 + nd) % (M + 1);
		}

		m = sort(m, N);
		n = sort(n, M);
		
		long[] accumN = new long[N + 1];
		long[] accumM = new long[M + 1];
		for (int i = 0; i < N; ++i) {
			accumN[i + 1] = accumN[i] + n[i];
		}
		for (int i = 0; i < M; ++i) {
			accumM[i + 1] = accumM[i] + m[i];
		}
		
		int cur = N;
		long sum = accumM[0] + accumN[cur] + (N - cur) * (M - 0);
		for (int i = 0; i <= M; ++i) {
			while (cur >= 1 && accumM[i] + accumN[cur] + (long)(N - cur) * (M - i) >= accumM[i] + accumN[cur - 1]
					+ (long)(N - (cur - 1)) *(M - i))
				--cur;
			sum = Math.min(sum, accumM[i] + accumN[cur] + (long)(N - cur) * (M - i));
		}
		
		System.out.println(sum);
		sc.close();
	}

	int[] sort(int[] a, int max) {
		int[] counter = new int[max + 1];
		for (int i = 0; i < a.length; ++i) {
			counter[a[i]]++;
		}
		int pos = 0;
		for (int i = 0; i < counter.length; ++i) {
			while (counter[i]-- > 0) {
				a[pos++] = i;
			}
		}
		return a;
	}

	void tr(Object... objects) {
		System.out.println(Arrays.deepToString(objects));
	}
}