Подсчёт количества масок среди данных, являющихся подмаской m, для всех m -- почему это работает?

Revision ru1, by popoffka, 2016-07-01 19:14:32

На олимпиаде Казахстана прошлого года была задача "Количество совместимых чисел", которая сводится к такой: даны 22-битные маски a1, a2, ..., an (n < 106), нужно посчитать d[m] — количество таких i, что a[i] является подмаской m (т.е. a[i] & m == a[i]).

Официальное решение решает эту задачу так:

for (int i = 0; i < n; i++) {
	d[a[i]]++;
}

for (int i = 0; i < 22; i++) {
	for (int mask = 0; mask < (1 << 22); mask++) {
		if ((mask & (1 << i)) == 0) {
			d[mask | (1 << i)] += d[mask];
		}
	}
}

Пытаясь решить эту задачу самостоятельно, я дошёл до этой идеи, но сразу отбросил, потому что мне показалось очевидным, что она какие-нибудь подмаски будет считать несколько раз. Сейчас я вроде бы почти убедил себя, что этого не происходит, но у всё ещё меня нет интуитивного понимания того, почему это должно работать. Может, это какой-то известный трюк, которого я не знаю? Или может просто кто-нибудь может объяснить логику этого подхода?

Спасибо!

Tags битмаски, вопрос

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
en1 English popoffka 2016-07-01 19:18:19 1023 Initial revision for English translation
ru1 Russian popoffka 2016-07-01 19:14:32 1095 Первая редакция (опубликовано)