april_day_2026/c/solution4.c
2026-03-28 18:14:57 +03:00

117 lines
3.8 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdlib.h> // atoi, malloc
void ten_to_bin(int count, long long x, char *mask) {
int i = 0;
while (i < count) {
mask[i] = (x & 1) + '0'; // Побитовое И вместо % 2
mask[i+1] = '\0';
x >>= 1; // Побитовый сдвиг вправо вместо / 2
i++;
}
}
long long calculate_sum(int count, int *numbers, long long x) {
long long sum = 0;
for (int j = 0; j < count; j++) {
// Проверяем, установлен ли j-й бит в числе x
if ((x >> j) & 1) {
sum += numbers[j];
}
}
return sum;
}
void find_sum(int count, long long target, int *numbers, char *mask) {
long long total_combinations = (1LL << count);
printf("Total combinations: %lld\n", total_combinations);
for (long long i = 0; i < total_combinations; i++) {
long long current_sum = 0;
// Развертывание цикла (Unrolling) + Избавление от if (Branchless)
// Процессор будет выполнять эти операции параллельно в конвейере
int j = 0;
// Разворачиваем по 2 шага для ускорения
for (; j <= count - 2; j += 2) {
current_sum += (long long)numbers[j] * ((i >> j) & 1);
current_sum += (long long)numbers[j + 1] * ((i >> (j + 1)) & 1);
}
// Добираем оставшиеся элементы, если count не кратен 2
for (; j < count; j++) {
current_sum += (long long)numbers[j] * ((i >> j) & 1);
}
if (current_sum == target) {
ten_to_bin(count, i, mask);
printf("OK: %s\n", mask);
return;
}
}
printf("NO: not found.\n");
}
void find_sum_old(int count, long long target, int *numbers, char *mask) {
// 1LL << count — это 2 в степени count (макс. 62 для long long)
long long total_combinations = (1LL << count);
printf("Total combinations: %lld\n", total_combinations);
for (long long i = 0; i < total_combinations; i++) {
long long current_sum = 0;
// Внутренний цикл: проверяем биты числа i напрямую
for (int j = 0; j < count; j++) {
// Используем умножение на бит вместо if, чтобы избежать ошибок в предсказании перехода
current_sum += numbers[j] * ((i >> j) & 1);
}
if (current_sum == target) {
ten_to_bin(count, i, mask);
printf("OK: %s\n", mask);
return;
}
}
printf("NO: not found.\n");
}
// gcc -O3 -march=bdver2 solution4.c -o solution
// gcc -O3 solution4.c -o solution -lm
// ./solution 477550 15800 1525 35300 19410 25000 15800 1525 35300 19410 25000
// 15800 1525 35300 19410 25000 15800 1525 35300 19410 25000 15800 1525 35300
// 19410 25000
int main(int argc, char *argv[]) {
// 1. Валидация ввода
if (argc < 5) {
printf("ER: input parameters \n");
return 1;
}
if (argc > 30) {
printf("ER: input parameters \n");
return 1;
}
// 2. Формирование массива int
long long target = atoi(argv[1]); // Требуемая сумма
int count = argc - 2; // Количество переданных чисел
int *numbers = malloc(count * sizeof(int)); // Создаем массив
for (int i = 0; i < count; i++) {
// Преобразуем каждый аргумент (начиная с argv[2]) в int
numbers[i] = atoi(argv[i + 2]);
}
// 3. Формирование массива char
char *mask =
calloc(count + 1, sizeof(char)); // +1 для символа конца строки '\0'
// 4. Данные готовы, начинаем считать
find_sum(count, target, numbers, mask);
// 5. Освобождаем память
free(mask);
free(numbers);
return 0;
}