powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Тяпничные лампочки
25 сообщений из 92, страница 3 из 4
Тяпничные лампочки
    #39170837
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr SharahovDima T, еще быстрее

Нет. Медленнее. 1,55 сек. Тут k надо перечитывать. У меня не надо. Она в регистре живет.

Можно еще подобным образом пошаманить над циклом заполнения
Код: plaintext
1.
2.
3.
4.
5.
				int lim = next - start; // конец биткарты
				register int v = values[i] - start, s = steps[i];
				for (; v < lim; v += s) {
					bm[v >> 3] ^= (1 << (v & 7));
				}


сделать обращение к биткарте 4хбайтным и v >> 3 как-то оптимизировать, т.к. в 32 бита по несколько раз много счетчиков попадает.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170841
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это шаманство дает копеечное ускорение. Я бы все-таки копал в сторону уменьшения количества счетчиков. Сейчас их 25. Шаг
Код: sql
1.
4 6 10 14 16 18 22 24 26 30 34 38 40 42 46 50 27 28 29 31 32 33 36 37 39 41 43 44 47 48 49


хотя бы как-то убрать самые частые: 4 6 10
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170842
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

Ясно.
С заполнением бит-карты вряд ли быстрее удастся.
Можно, конечно, немного поиграть с разворачиванием цикла.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170847
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Посчитал сколько бит сбрасывается из 1 в ноль
Код: plaintext
1.
2.
3.
4.
				for (; v < lim; v += s) {
					if ((bm[v >> 3] & (1 << (v & 7))) != 0) cnt_bad++;
					bm[v >> 3] ^= (1 << (v & 7));
				}


Код: sql
1.
cnt_bad 429321267


потенциальная возможность для ускорения совершенствованием алгоритма.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170850
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TЭто шаманство дает копеечное ускорение. Я бы все-таки копал в сторону уменьшения количества счетчиков. Сейчас их 25. Шаг
Код: sql
1.
4 6 10 14 16 18 22 24 26 30 34 38 40 42 46 50 27 28 29 31 32 33 36 37 39 41 43 44 47 48 49


хотя бы как-то убрать самые частые: 4 6 10

счетчики 4, 16, 32, 34, 36, 40, 48 можно сделать двумя битовыми масками
при подсчете результата, если цикл развернуть еще вдвое.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170856
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahov, ошибочка

только счетчики 4, 16, 32 можно сделать одной битовой маской при подсчете результата
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170858
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr Sharahovсчетчики 4, 16, 32, 34, 36, 40, 48 можно сделать двумя битовыми масками
при подсчете результата, если цикл развернуть еще вдвое.
не понял о чем речь, давай поподробнее.

только не забывай что мы их уже один раз модифицировали 18815259 :
4 это 2+4k, т.е. с 2 шаг 4
16 это 8+16k
и т.д.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170861
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

по всем счетчикам, на которые делится 32
(они дают повторы битов через 32)
один раз формируем маску mask, и далее

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
for (int i = 0; i < BM_SIZE; i += 4) {
				unsigned int k = *((int*)&bm[i]) xor mask;
				res += bit_cnt[k & 0xFF];
				k >>= 8;
				res += bit_cnt[k & 0xFF];
				k >>= 8;
				res += bit_cnt[k & 0xFF];
				k >>= 8;
				res += bit_cnt[k & 0xFF];
				*((int*)&bm[i]) = 0;
			}



естественно, эти счетчики не участвуют в заполнении бит-карты.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170865
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
последействие паскаля, вместо xor надо было ^
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170868
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr SharahovDima T,

по всем счетчикам, на которые делится 32
(они дают повторы битов через 32)
один раз формируем маску mask, и далее
понял, сегодня уже плохо соображаю, завтра затестю.
Я еще голову ломаю как бы счетчики с отношением 3 склеить. Там шаг должен быть 1,2,1,2 т.е. можно менять шаг битовым сдвигом туда-обратно после каждого шага. Это в мыслях пока.

текущий вариант исходника
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
#include <fstream>
#include <iostream>
using namespace std;

#include <stdio.h>
#include <time.h>
#include <string.h>

// Размер окна биткарты в байтах
#define BM_SIZE 8192 // 8 Kb

int main(int argc, char**argv)
{
	// Считывание задания
	ifstream in("input.txt");
	int N, K;
	in >> N >> K;
	bool P[51] = { 0 };
	int cnt = 0; // кол-во полезных счетчиков
	for (int i = 0; i < K; i++) {
		int v;
		in >> v;
		P[v] = !P[v];
		if (P[v]) {
			cnt++;
		} else {
			cnt--;
		}
	}
	if (P[1]) cnt--; // единицы не считаем

	int res = 0;
	if (cnt) {
		int* steps = (int*)calloc(cnt, sizeof(int)); // шаги счетчиков
		int* values = (int*)calloc(cnt, sizeof(int)); // значения счетчиков
		for (int i = 2, j = 0; i <= 50; i++) {
			if (P[i]) {
				if(i <= 25 && P[i * 2]) {
					// Объединение счетчиков с шагом отличающимся вдвое
					steps[j] = i * 2;
					values[j] = i;
					P[i * 2] = false;
					cnt--;
				} else {
					steps[j] = i;
					values[j] = i;
				}
				j++;
#ifdef _DEBUG
				cout << steps[j - 1] << " ";
#endif
			}
		}
		// Для подсчета единичных бит в байте
		int bit_cnt[256] = { 0 };
		for (int i = 0; i < 256; i++) {
			int n = i;
			while (n != 0) {
				bit_cnt[i]++;
				n &= (n - 1);
			}
		}
		// Биткарта
		unsigned char* bm = (unsigned char*)calloc(BM_SIZE, 1);
		int next = 0;
		//int cnt_bad = 0;
		while (next <= N) {
			int start = next;
			next += BM_SIZE * 8;
			if (next > N) next = N + 1;
			// Заполнение окна биткарты
			for (int i = 0; i < cnt; i++) {
				int lim = next - start; // конец биткарты
				register int v = values[i] - start, s = steps[i];
				for (; v < lim; v += s) {
					//if ((bm[v >> 3] & (1 << (v & 7))) != 0) cnt_bad++;
					bm[v >> 3] ^= (1 << (v & 7));
				}
				values[i] = v + start;
			}
			// считывание результата
			for (int i = 0; i < BM_SIZE; i += 4) {
				register unsigned int k = *((int*)&bm[i]);
				res += bit_cnt[k & 0xFF];
				res += bit_cnt[(k >> 8) & 0xFF];
				res += bit_cnt[(k >> 16) & 0xFF];
				res += bit_cnt[k >> 24];
				*((int*)&bm[i]) = 0;
			}
		}
		//cout << "cnt_bad " << cnt_bad << endl;
	}
	// Инверсия если была единица
	if (P[1]) res = N - res;
	// Вывод результата
	ofstream out("output.txt");
	out << res << endl;
	out.close();
	cout << endl << "time " << clock() << endl;
	cout << "Result " << res << endl;
	return 0;
}

...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170872
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T
Я еще голову ломаю как бы счетчики с отношением 3 склеить.
Там шаг должен быть 1,2,1,2 т.е. можно менять шаг битовым сдвигом туда-обратно после каждого шага.


Это просто: step=3-step.
Придется хранить не 2, а 3 описателя для каждого счетчика.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170876
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, не будет так быстрее?

Код: plaintext
1.
2.
3.
4.
res += bit_cnt[k & 0xFF]
	+ bit_cnt[(k >> 8) & 0xFF]
	+ bit_cnt[(k >> 16) & 0xFF]
	+ bit_cnt[k >> 24];
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170879
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr SharahovКстати, не будет так быстрее?

Код: plaintext
1.
2.
3.
4.
res += bit_cnt[k & 0xFF]
	+ bit_cnt[(k >> 8) & 0xFF]
	+ bit_cnt[(k >> 16) & 0xFF]
	+ bit_cnt[k >> 24];


так еще медленнее. Что-то у меня 1,15 сек 18815517 опять вырасли до 1,4. хз чего направил завтра перепроверю.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170880
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tпонял, сегодня уже плохо соображаю, завтра затестю.


Там есть пара тонких мест:
1) кратность размера окна 4 байтам (32 битам) - ну это и так есть,
2) кратность общего количества лампочек 32 - если ее нет,
то придется вычесть лишние висячие биты маски.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170886
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr SharahovDima Tпонял, сегодня уже плохо соображаю, завтра затестю.


Там есть пара тонких мест:
1) кратность размера окна 4 байтам (32 битам) - ну это и так есть,
2) кратность общего количества лампочек 32 - если ее нет,
то придется вычесть лишние висячие биты маски.
1. есть
2. есть. Заполнение биткарты счетчиками заканчивается на N, а вот с масками на 4,16,32 это надо будет учесть.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170889
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ого тут букв!

А пробовали учесть повторы делителей 3,4,5 ?

Код: sql
1.
1 2 7 3*3 13 4*4 19 23 5*8 5*9
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170901
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

пока что ясно:
1) шаги 2, 4, 8, 16, 32 учитываются одной общей маской при подсчете суммы,
2) шаги X и 2X заменяются одним сдвинутым шагом 2X,
3) шаги X и 3X заменяются одним переменным сдвинутым шагом 2X/2

остальное пока неясно.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170908
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
опечатка
3) шаги X и 3X заменяются одним переменным сдвинутым шагом 2X/X
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39170995
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Восстановил исходник, который работал 1,15 сек.

ИМХУ склеивание счетчиков тупиковый путь. Для того что очевидно как клеить (типа кратных двум) скорее всего сделали тесты так чтобы клеить было нечего.

Переделал наихудшие тесты с учетом нашей оптимизации по склеиванию кратных двум.
это считается 1,75 сек
Код: sql
1.
2.
1000000000 32
1 2 3 5 7 9 11 13 15 17 19 23 25 27 28 29 31 32 33 45 36 37 39 40 41 42 43 44 45 47 48 49


это считается 1,4 сек и никак не склеится
Код: sql
1.
2.
1000000000 16
2 3 5 7 11 13 17 19 23 29 31 37 39 41 43 47


Мне кажется надо в первую очередь оптимизировать малые счетчики, т.к. там проходов больше всего
СчетчикИтерацийДоля250000000014.3%33333333339.5%42500000007.1%52000000005.7%61666666664.8%71428571424.1%81250000003.6%
Счетчики 2,4,8,16,32 суммарно 27,7% итераций. Оптимизация масками должна заметно их ускорить.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171002
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Любые малые счетчики можно масками наносить, просто надо сдвиг дополнительный, например для 3x:
Код: sql
1.
2.
3.
4.
5.
01001001
10010010
00100100
01001001
...


для 5 уже таблица сдвигов [3,1,4,2 ...]

Думаю можно развить эту идею: 18815352 заготовить каждому счетчику биткарту выравненную по 4 байтам и наносить счетчики биткартами. В каждой биткарте байт будет не более значение счетчика * 4.

Для 2,4,8,16,32 можно одну общую биткарту использовать.

Для счетчиков кратных 2,4,8,16 тоже общие биткарты можно. Например 5, 20, 40 должны объединиться на биткарте 40, если не напутал.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171010
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T, думаю, ощутимый выигрыш даст только маска для степеней двойки.

Для других сдвигов маска малопригодна,
т.к. придется работу переносить в подсчет,
а там будет довольно накладно запоминать
состояния переменного числа шагов.

Ну, может быть, стоит шаг=3 отдельно учесть.
Т.е. делаем размер окна кратным 12 байт,
и если тройка есть среди множителей,
то подсчет идет другим циклом, развернутым в 3 раза.
Можно и подсчет без тройки тоже развернуть.

И, думаю, от склейки по 2 не стоит отказываться, т.к. она дается даром.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171013
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Склейка 1 к 3 или 2 к 3 тоже достаточно дешева:
для всех таких (1 к 3 или 2 к 3) заполнение окна
делаем в другом цикле, который отличается от твоего
одним лишним вычитанием в теле цикла step=m-step
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171016
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ты не понял, для счетчика один раз инициализируется биткарта, примеры на 8-битовых (биты в обратном порядке 0-7 для наглядности):
Код: sql
1.
2.
3.
3 = 10010010,01001001,00100100
5 = 10000100,00100001,00001000,01000010,00010000
6 = 10000010,00001000,00100000,10000010,00001000,00100000


дальше просто зацикливаем маску и по кругу.

Предыдущая оптимизация с двойками не теряется, но и добавляются новые. Например маска для 3 дважды ложится в 6, т.е. их склеиваем при инициализации. То же самое с 12, туда лезут 3,6. В 48 влезут 2,3,4,6,8,12,16,24.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171018
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем вся математика на этапе инициализации, во время расчета тупо XOR двойными словами( по 32 бита) и подсчет результатов.
Даже изврата с единицей не надо, ее в любую маску можно добавить.
Должно сработать.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171020
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я понял, потому что думал над этим раньше )
Тут очень большая проблема, которая почти наверняка потребует
создание внутреннего цикла внутри подсчета и работы с памятью.

Тройку (и если хочешь простыню - пятерку) можно учесть
масками без доп. работы, если развернуть цикл.
Но не более.
...
Рейтинг: 0 / 0
25 сообщений из 92, страница 3 из 4
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Тяпничные лампочки
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]