powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Тяпничные лампочки
17 сообщений из 92, страница 4 из 4
Тяпничные лампочки
    #39171024
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
разумеется, при этом под оптимизацию попадают все делители чисел 96 и 160
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171025
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вторым шагом можно досклеить полученные биткарты пока пямяти хватает: например 13 и 17 склеятся в 884 байта (13 * 17 * 4). Хотя тут не факт что ускорение будет, т.к. маленькие вместе влезут в кэш проца, большие будут из памяти подкачиваться постоянно. С другой стороны чем меньше биткарт, тем быстрее будет считаться.

Пока некогда, ближе к вечеру постараюсь написать.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171411
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Написал. Летает. 50 счетчиков до лярда 0,2 сек.

Но это 0.42 сек.
Код: sql
1.
2.
1000000000 17
2 3 5 7 11 13 17 19 23 29 31 37 39 41 43 47 49



медленнее потому что склейка счетчиков не самая лучшая. В первом случае 50 склеилось в 4 счетчика, во втором всего в 9, хотя можно минимум в 4.

Надо какой-то оптимальный алгоритм склейки. Суть в следующем:
счетчик a занимает size_a = НОК(а,4) байта, счетчик b - size_b = НОК(b,4) байт, при слиянии займут size_ab = НОК(size_a, size_b)
например а = 11 тогда size_a = 44, b = 18 => size_b = 36, после слияния счетчик ab займет size_ab = 396
И тут их надо так слить чтобы суммарно они не вылезли за 16 Мб. Я поставил 14.
ХЗ как комбинировать. Пока сделал так: берем последний, поиск такого с которым size_ab минимальное, если нашли и памяти достаточно - слияние.

ХЗ как оптимизировать. Факторизация и ... ?

PS Сайт для проверки лежит, пока не затестить, но думаю пройдет тест. Исходник выкладывать или пусть желающие сами пишут по инструкции выше ?
PPS Ссылку Fort Knox почитал по диагонали, нифига не понял.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171426
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Или по другому, в случае ряда простых чисел типа
Код: sql
1.
3 5 7 11 13 17


разбить их на минимальное количество групп, так чтобы сумма произведений членов каждой группы была меньше заданного предела.
например две группы
Код: sql
1.
(3*5*7) + (11*13*17) < MAX


Если в одну не сливается, то данное решение уже идеально, т.к. принципиально минимизировать количество групп, а не результат.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171495
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
50 в 4 слилось так (лог)
Код: sql
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.
Исходный -> групповой
50->0
49->1
48->2
47->3
46->4
44->5
43->6
42->7
41->8
40->0
39->9
38->10
37->11
36->12
34->13
33->14
32->0
31->15
30->16
29->17
28->1
27->18
26->9
25->0
24->2
23->4
22->5
21->7
20->0
19->10
18->12
17->13
16->0
15->16
14->1
13->9
12->2
11->5
10->0
9->12
8->0
7->1
6->2
5->0
4->0
3->2
2->0
1->0
Слияние групповых
[18] => [2]
[17] => [12]
[16] => [0]
[15] => [5]
[14] => [7]
[13] => [10]
[12] => [2]
[11] => [4]
[10] => [9]
[9] => [0]
[8] => [6]
[7] => [1]
[6] => [3]
[5] => [1]
[4] => [2]

при загрузке склеиваются только если меньший влазит в больший кратно 2 раз
ГрупповойИсходные01 2 4 5 8 10 16 20 25 32 40 5017 14 28 4923 6 12 24 483 474 23 46511 22 44643721 42841913 26 391019 381137129 18 361317 34143315311615 3017291827

После слияния групповых стало так
ГрупповойИсходные01 2 4 5 8 10 16 20 25 32 40 50 15 30 13 26 39 19 38 17 3417 14 28 49 21 42 33 11 22 44 3123 6 12 24 48 27 9 18 36 29 23 46 373 47 43 41
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171520
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TНаписал. Летает.

Здорово, если пройдет тест на скорость.

Dima TСсылку Fort Knox почитал по диагонали, нифига не понял.

Дык, XOR множеств.
Отличие от формулы включений-исключений только в том,
что надо дважды вычитать то, что пересеклось.

По идее слагаемых должно быть 2^x,
но реально их намного меньше,
т.к. лампочки, входящие в пересечение нескольких множеств
часто оказываются дальше последней.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171618
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T, я чувствуется опыт Решета Эратосфена.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171775
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonDima T, я чувствуется опыт Решета Эратосфена.
Тут все из него. От теории до реализации.

Придумал оптимизацию счетчиков. Сворачивается в 4 счетчика. Время 0.3-0.4 сек на самых тяжелых случаях.

Никто не высказался против выкладывания исходника, поэтому выкладываю. Думаю рядовым студентам он бесполезен, а олимпийцы только опыта поднаберутся. Тупым гуглением олимпиаду не выиграть.
Исходник (многа букав)
Код: 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.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
// http://acmp.ru/index.asp?main=task&id_task=337

#include <fstream>
#include <iostream>
#include <vector>
#include <map>
using namespace std;

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

//#define MAX_MEMORY 4194304 // 4 Мб
//#define MAX_MEMORY 8388608 // 8 Мб
#define MAX_MEMORY 14680064 // 14 Мб

// НОД
int64_t gcd(int64_t a, int64_t b) {
	return b ? gcd(b, a % b) : a;
}

// НОK
int64_t lcm(int64_t a, int64_t b) {
	return a / gcd(a, b) * b;
}

//Макс простой множитель
int max_prime(int n) {
	static int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 };
	if (n == 1) return 1;
	int* m = primes;
	while(n > 1) {
		if((n % *m) == 0) {
			n /= *m;
		} else {
			m++;
		}
	}
	return *m;
}

// Класс счетчика
class cnt_t {
	uint32_t* bm; // биткарта
	size_t size; // Размер в битах
	uint32_t* cur; // текущий элемент для перебора
	uint32_t* end; // конец bm
public:
	cnt_t() {
		bm = NULL;
	}

	~cnt_t() {
		if(bm != NULL) free(bm);
	}

	// Инициализация
	void init(int value) {
		size = lcm(value, 32);
		bm = (uint32_t*)calloc(size / 32, 4);
		cur = bm;
		end = bm + (size / 32);
		for (uint32_t i = 0; i != size; i += value) {
			bm[i >> 5] ^= (1 << (i & 31));
		}
	}

	// Склеивание с другим счетчиком
	bool clue(cnt_t& c) {
		size_t new_size = lcm(size, c.size);
		if(new_size > size) {
			uint32_t* bm_new = (uint32_t*) realloc(bm, new_size / 8);
			if (!bm_new) return false;
			bm = bm_new;
			cur = bm;
			end = bm + (size / 32);
			uint32_t* new_end = bm + (new_size / 32);
			for (uint32_t* p = end; p < new_end; p++) {
				*p = next();
			}
			size = new_size;
			cur = bm;
			end = new_end;
		}
		c.cur = c.bm;
		for (uint32_t* p = bm; p < end; p++) {
			*p ^= c.next();
		}
		return true;
	}

	// Склеивание с другим исходным счетчиком
	bool clue(int i) {
		if(add(i)) {
			return true;
		} else {
			cnt_t c;
			c.init(i);
			return clue(c);
		}
	}

	// Добавление счетчика. Возвращает false - если невозможно добавить
	bool add(int value) {
		size_t new_size = lcm(value, 32);
		if (size != new_size && size % new_size != 0) {
			// Не входит кратно
			return false;
		}
		for (uint32_t i = 0; i != size; i += value) {
			bm[i >> 5] ^= (1 << (i & 31));
		}
		return true;
	}

	// Перенос в другой счетчик
	void move(cnt_t& c) {
		if (c.bm != NULL) free(c.bm);
		c.bm = bm;
		c.cur = cur;
		c.end = end;
		c.size = size;
		bm = NULL;
	}

	// Занято памяти, байт
	uint32_t total() {
		return size / 8;
	}

	// Следующие 32 бита (лампочки)
	uint32_t next() {
		if (cur == end) cur = bm;
		return *(cur++);
	}
};


int main(int argc, char**argv)
{
	// Считывание задания
	ifstream in("input.txt");
	int N, K;
	in >> N >> K;
	bool P[51] = { 0 };
	for (int i = 0; i < K; i++) {
		int v;
		in >> v;
		P[v] = !P[v];
	}
	// Распределение по счетчикам (для каждого mp свой счетчик)
	vector<cnt_t> counters;
	map<int, int> mp_idx;
	counters.reserve(12);
	int k_init = 0;
	for (int i = 50; i > 0; i--) {
		if (P[i]) {
			k_init = 1 - k_init;
			int mp = max_prime(i);
			if (mp < 11) mp = 11; // все маленькие в один
			map<int, int>::iterator it = mp_idx.find(mp);
			if (it != mp_idx.end()) { // Счетчик уже есть
				if (!counters[it->second].clue(i)) {
					it = mp_idx.end(); // Не склеилось
				} else {
#ifdef _DEBUG
					cout << endl << i << "->" << it->second;
#endif
				}
			}
			if(it == mp_idx.end()) { // Добавление счетчика
				counters.push_back(cnt_t());
				counters[counters.size() - 1].init(i);
				mp_idx[mp] = counters.size() - 1;
#ifdef _DEBUG
				cout << endl << i << "->" << mp_idx[mp];
#endif
			}
		}
	}
	int total = 0;
	for (int i = 0; i < counters.size(); i++) {
		total += counters[i].total();
	}
#ifdef _DEBUG
	cout << endl << "memory " << total;
#endif
	// Склеивание счетчиков
	int prev = 0;
	while(prev != counters.size()) {
		prev = counters.size();
		// поиск минимального
		int add_idx = prev - 1;
		int size_test = counters[add_idx].total();
		for (int i = 0; i < prev - 2; i++) {
			if(size_test > counters[i].total()) {
				size_test = counters[i].total();
				add_idx = i;
			}
		}
		int64_t min = MAX_MEMORY - total + size_test;
		int min_idx = prev;
		// Поиск наименьшего размера после склеивания
		for (int i = 0; i < prev; i++) {
			if (i == add_idx) continue;
			int64_t new_size = lcm(size_test, counters[i].total());
			if(min > new_size) {
				min = new_size;
				min_idx = i;
			}
		}
		if(min_idx != prev) {
			total += (int)min - size_test;
			if (total > MAX_MEMORY) break;
			if(counters[min_idx].clue(counters[add_idx])) {
#ifdef _DEBUG
				cout << endl << "[" << add_idx << "] => [" << min_idx << "] " << "memory " << total;
#endif
				if(add_idx != prev - 1) { // непоследний
					counters[prev - 1].move(counters[add_idx]);
				}
				counters.pop_back();
			}
		}
	}
	cout << endl << "counters " << counters.size() << " memory " << total / 1024 << "Kb";
	// Для подсчета единичных бит в байте
	int bit_cnt[256] = { 0 };
	for (int i = 0; i < 256; i++) {
		int n = i;
		while (n != 0) {
			bit_cnt[i]++;
			n &= (n - 1);
		}
	}
	// Расчет
	int res = 0;
	cnt_t* start = &counters[0];
	cnt_t* end = start + counters.size();
	int next = 0;
	register uint32_t k = k_init;
	while (true) { // Самый тяжелый цикл
		// Очередная порция лампочек
		for (cnt_t* c = start; c < end; c++) {
			k ^= c->next();
		}
		next += 32;
		// подсчет лампочек (бит)
		if(next <= N) {
			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];
			k = 0;
		} else {
			for (int i = next - 32; i <= N; i++) {
				if ((k & 1) != 0) res++;
				k >>= 1;
			}
			break;
		}
	}
	// Вывод результата
	ofstream out("output.txt");
	out << res << endl;
	out.close();
	cout << endl << "time " << clock() << endl;
	cout << "Result " << res << endl;
	return 0;
}



PS На проверку не отправил, т.к. сайт-проверялка лежит. У меня итого сходится с предыдущими реализациями. Завтра утром зашлю, если оживет.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39171977
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonDima T, я чувствуется опыт Решета Эратосфена.
Только сейчас понял что тогда к Эратосфену надо было прикрутить эту идею со склеивающимися счетчиками, а то я какие-то велосипеды с квадратными колесами изобретал в виде счетчиков с переменным шагом 17486621 . В итоге вся оптимизация закончилась на 3-ке, а так можно заготовку биткарты сделать и ее использовать для инициализации (для 2,3,5,7,11 потребуется всего 9 Кб). Надо будет добавить туда как-нибудь. А то я там "рекорды" ставил распараллеливанием на 4 ядра. Судя по этим замерам там тоже должно ускориться в 3-5 раз.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39177350
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Задача сдана ? Не могу даже условие посмотреть
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39177848
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не сдана. Там все сломалось
http://acmp.ru/index.asp?r=151923784153675657266782 [20.02] Уважаемые пользователи! В связи с техническими сложностями (вышел из строя веб-сервер) сайт был недоступен и в настоящее время используется его копия. В связи с малой мощностью предоставленного сервера возможность авторизации пользователям будет ограничена (участники раздела "Курсы", спонсоры и т.д. смогут решать задачи в любое время, остальные - по воскресеньям и с 17:00 до 4:00 в другие дни)...
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39179142
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот к чему приводит возведение 99 десять раз в степень 99.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39179174
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Заслал на проверку. Прошел все тесты. Время 0,397 сек.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39179239
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ты крут как варёные яйца.

А я щас делаю задачу с укладкой домино.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39179290
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonТы крут как варёные яйца.

А я щас делаю задачу с укладкой домино.
в пятничную тему не выноси. Не сдержусь
Работы навалили со всех сторон одновременно. Я в Эратосфена начал вписывать то что тут родилось, взлетел он немного с 23 до 27 млн в сек., но не все дописал. Мысли еще есть, времени пока нет. С паспортами тоже почти закончил 18772620 , чуть-чуть доделать, потестить и готовый продукт будет.
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39179463
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TЗаслал на проверку. Прошел все тесты. Время 0,397 сек.

Поздравляю ;)
...
Рейтинг: 0 / 0
Тяпничные лампочки
    #39179680
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TmaytonТы крут как варёные яйца.

А я щас делаю задачу с укладкой домино.
в пятничную тему не выноси. Не сдержусь
Работы навалили со всех сторон одновременно. Я в Эратосфена начал вписывать то что тут родилось, взлетел он немного с 23 до 27 млн в сек., но не все дописал. Мысли еще есть, времени пока нет. С паспортами тоже почти закончил 18772620 , чуть-чуть доделать, потестить и готовый продукт будет.
И не подумаю. Я до 4.00 утра просидел с домино. Пока не понял что алгоритм волны не покрывает
общий случай. И нужен поиск в глубину.

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


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