Дан набор из N целых положительных чисел. Из этих чисел формируются все возможные пары (парой считаются два элемента, которые находятся на разных местах в наборе, порядок чисел в паре не учитывается), в каждой паре
вычисляется сумма элементов. Необходимо определить количество пар, для которых полученная сумма делится на 8.
Напишите эффективную по времени и по памяти программу для решения этой задачи.
Программа считается эффективной по времени, если при увеличении количества исходных чисел N в k раз время работы программы увеличивается не более чем в k раз.
Программа считается эффективной по памяти, если память, необходимая для хранения всех переменных программы, не превышает одного килобайта и не увеличивается с ростом N.
Максимальная оценка за правильную (не содержащую синтаксических ошибок и дающую правильный ответ при любых допустимых входных данных) программу, эффективную по времени и по памяти, – 4 балла.
Максимальная оценка за правильную программу, эффективную только по времени или только по памяти, – 3 балла.
Максимальная оценка за правильную программу, не удовлетворяющую требованиям эффективности, – 2 балла.
Вы можете сдать одну или две программы решения задачи. Если Вы сдадите две программы, каждая из них будет оцениваться независимо от другой,
итоговой станет бо́льшая из двух оценок.
Перед текстом программы кратко опишите алгоритм решения. Укажите использованный язык программирования и его версию.
Описание входных и выходных данных
В первой строке входных данных задаётся количество чисел N (1 ≤ N ≤ 1000).
В каждой из последующих N строк записано одно натуральное число, не превышающее 10 000.
Пример входных данных:
5
1
5
7
11
1
Пример выходных данных для приведённого выше примера входных данных: 3
Из 5 чисел можно составить 10 пар. В данном случае у трёх пар сумма делится на 8: 1 + 7, 1 + 7 (в наборе две единицы, поэтому пару 1+7 можно составить двумя способами), 5 + 11
Решение:
var a: array[0..7] of Integer;
q,n,i,s,s0,s1,s2,s3,s4: Integer;
begin
ReadLn(n);
for i:=1 to N do begin
ReadLn(q);
a[q mod 8]:=a[q mod 8]+1;
end;
s0:=a[0]*(a[0]-1) div 2;
s4:=a[4]*(a[4]-1) div 2;
s1:=a[1]*a[7];
s2:=a[2]*a[6];
s3:=a[3]*a[5];
s:=s0+s4+s1+s2+s3;
WriteLn(s);
end.
Краткое объяснение
Идея решения заключается в использовании частотного массива для хранения остатков от делений введенных чисел. Подсле того, как частотный массив заполнен мы должны подсчитать сколько сочетаний может быть для различных чисел.
Например, если есть 2 числа, которые в остатке дают 1 и 2 числа которые в остатке дают 7, то каждое число, которое делится на 1, может образовать с 2 числами пару из тех, которые в остатке дают 7, то есть это их произведение.
Если же число делится на 8, то каждое число, которое делится на 8, может сочетать с другими числами, которые делятся на 8.
Например, у нас 4 числа, которые делятся на 8 (8, 16, 24, 32), тогда
1 число образует пару еще с 3 числами, 3
1 число образует пару еще с 2 числами, 2
1 число образует пару еще с одним числом. 1
То есть это арифметическая прогрессия от 1 до (4-1). То есть (1-(4-1)/2*3=4/2*3 или 4*3 div 2.
С числами, которые делятся на 4 та же ситуация что и с числами, которые делятся на 8.
Итог — это сумма всех сочетаний