Розбір
Автор: Єгор Дубовік
Розробник: Ігор Баренблат
Визначимо — вираз, що означає, що ( є «підмаскою» ). Тут — побітове І.
Розв'язуватимемо задачу покроково.
Визначимо — -бітова маска, де -ий біт рівний , якщо місто з номером належить списку з номером , та в протилежному випадку.
Як порахувати ? Це домашнє завдання :)
Визначимо — кількість таких , що .
Як порахувати ? Це домашнє завдання :)
Визначимо — кількість авіашляхів, що можуть утворитися за використання будь-якого зі списків, що відповідають одиничним бітам -бітової маски .
Як порахувати ? (Для того щоб швидко порахувати значення, використовуйте ідею
super magic algo
(описано нижче)).Визначимо — кількість авіашляхів, що будуть утворені за використання списків, що відповідають одиничним бітам -бітової маски (помітимо, що це значення не залежить від порядку використання списків).
Як порахувати ? Посилаючись на формулу включень-виключень, отримуємо: (Для того щоб швидко порахувати значення, використовуйте
super magic algo
(описано нижче)). Тут — кількість одиничних бітів маски .Розв'язуватимемо задачу методом динамічного програмування. Визначимо — максимальна кількість грошових одиниць, які можна заробити, використавши списки, що відповідають одиничним бітам -бітової маски у довільному порядку.
Як порахувати ? . , де — номери одиничних бітів -бітової маски . Тут — побітове виключне АБО.
Відповіддю до задачі є .
/// super magic algo
Нехай задається масив розміру . Необхідно знайти значення масиву , де .
Здійснимо ітерацій, де після ітерації з номером значенням буде , таких що , та починаючи з біта з номером біти чисел та збігаються (біти нумеруються з 0).
Очевидно, що перед першою ітерацією . На ітерації з номером перерахуємо .
Якщо в числі x біт з номером рівний , то .
Якщо в числі x біт з номером рівний , то .
Отже, легко реалізувати цей алгоритм так:
for (int i=0;i<(1<<m);i++){ b[i]=a[i]; } for (int i=0;i<m;i++){ for (int mask=0;mask<(1<<m);mask++){ if (mask&(1<<i)){ b[mask]+=b[mask^(1<<i)]; } } }
/// end of super magic algo
Складність часу та пам'яті.