Имеются две строки. На верхней строке отмечено a точек, а на нижней b точек. Соединим отрезком каждую точку
верхней строки с каждой точкой нижней строки. Точки расположены так, что
количество точек, полученных в результате пересечения отрезков, максимально.
Для достижения этой цели достаточно чтобы никакие три отрезка не пересекались в
одной точке. Точки на верхней и нижней строках в подсчет не включаются, в них
могут пересекаться любое количество отрезков. По значениям a и b Вам необходимо
вычислить P(a, b) – максимальное количество точек пересечения, расположенное между
двумя строками. Например, пусть a = 2
и b = 3. Из рисунка видно, что P(2,
3) = 3.
Вход. Каждая строка
содержит два натуральных числа a (0
< a ≤ 20000) и b (0 < b ≤ 20000). Последний тест содержит два нуля и не
обрабатывается. Входные данные содержат не более 1200 тестов.
Выход. Для каждого
теста в отдельной строке вывести его номер и значение P(a, b). Результат
помещается в 64-битовое знаковое целое.
Пример
входа |
Пример
выхода |
2 2 2 3 3 3
0 0 |
Case 1: 1 Case 2: 3 Case 3: 9 |
комбинаторика
Обозначим через
f(a, b) искомое количество точек пересечения. Очевидно, что f(1, b)
= 0, так как при a = 1 никакие два отрезка не пересекаются:
Рассмотрим общий
случай. Пусть x1, x2, …, xa
– точки на первой прямой, y1,
y2, …, yb – точки на второй прямой.
Соединим точку x1 с точками y1, y2,
…, yb. На отрезке x1y1
точек пересечения не будет. На отрезке x1y2
будут лежать точки пересечения с отрезками y1x2,
y1x3, …, y1xa
(всего a – 1 точек). На отрезке x1yj
будут лежать точки пересечения с отрезками yixk,
где i < j, 2 £ k £ a (всего (j – 1) * (a – 1) точек).
Количество точек пересечения, которые лежат на отрезках исходящих из x1,
равно (0 + 1 + 2 + … + (b – 1)) * (a – 1) = b * (b
– 1) / 2 * (a – 1).
Итак, из f(a,
b) точек b * (b – 1) / 2 * (a – 1) точек лежат на
отрезках исходящих из x1, а остальные точки лежат на отрезках
с концами в x2, …, xa. Имеем рекуррентное
соотношение:
f(a, b)
= b * (b – 1) / 2 * (a – 1) + f(a – 1, b)
Развернув его,
получим:
f(a, b)
= b * (b – 1) / 2 * (a – 1) + f(a – 1, b) =
b * (b –
1) / 2 * (a – 1) + b * (b – 1) / 2 * (a – 2) + f
(a – 2, b) = ... =
b * (b –
1) / 2 * (a – 1) + b * (b – 1) / 2 * (a – 2) + ... + b * (b – 1) / 2 * 1 =
b * (b –
1) / 2 * ( (a – 1) +
(a – 2) + ... + 1) =
b * (b –
1) / 2 * a * (a – 1) / 2
Таким образом,
максимальное количество точек пересечения равно
*
Пример
Рассмотрим
второй тест, для которого a = 2, b = 3. Максимально возможное
количество точек пересечения отрезков равно 3 и показано на рисунке:
Читаем входные
данные и для каждого теста вычисляем результат по выше приведенной формуле. При
заданных ограничениях на a и b в умножении переполнения не будет,
если вычисления проводить в 64-битовом целочисленном типе.
cs = 1;
while(scanf("%lld
%lld",&a,&b), a + b > 0)
{
res = a * (a - 1) * b * (b - 1) / 4;
printf("Case
%d: %lld\n",cs++,res);
}
Java
реализация
import java.util.*;
public class Main
{
public static void main(String[] args)
{
Scanner con = new
Scanner(System.in);
int cs = 1;
while(true)
{
long a = con.nextLong();
long b = con.nextLong();
if (a + b == 0) break;
long res = a * (a - 1) * b * (b - 1) / 4;
System.out.println("Case " + cs++ + ": " + res);
}
con.close();
}
}