Додавши до великої відповіді FatalError, рядок return f(b)^f(a-1);можна було б пояснити краще. Якщо коротко, це тому, що XOR має такі чудові властивості:
- Це асоціативно - розміщуйте дужки куди завгодно
- Це комутативно - це означає, що ви можете переміщати операторів (вони можуть "комутувати")
Ось обидва в дії:
(a ^ b ^ c) ^ (d ^ e ^ f) = (f ^ e) ^ (d ^ a ^ b) ^ c
Подобається це:
a ^ b = c
c ^ a = b
Додавання та множення - це два приклади інших асоціативних / комутативних операторів, але вони не змінюють себе. Ну так, чому ці властивості важливі? Ну, простий маршрут - це розширити його на те, що він є насправді, і тоді ви зможете побачити ці властивості на роботі.
Спочатку давайте визначимо, що ми хочемо, і назвемо це n:
n = (a ^ a+1 ^ a+2 .. ^ b)
Якщо це допомагає, подумайте про XOR (^) так, ніби це додаток.
Давайте також визначимо функцію:
f(b) = 0 ^ 1 ^ 2 ^ 3 ^ 4 .. ^ b
bбільший за a, тому просто безпечно потрапляючи в кілька додаткових дужок (що ми можемо, оскільки це асоціативно), ми також можемо сказати це:
f(b) = ( 0 ^ 1 ^ 2 ^ 3 ^ 4 .. ^ (a-1) ) ^ (a ^ a+1 ^ a+2 .. ^ b)
Що спрощує:
f(b) = f(a-1) ^ (a ^ a+1 ^ a+2 .. ^ b)
f(b) = f(a-1) ^ n
Далі ми використовуємо цю властивість зворотного зв'язку та комунікативність, щоб дати нам магічну лінію:
n = f(b) ^ f(a-1)
Якби ви думали про XOR як про додавання, ви б там упустили віднімання. XOR - XOR, що додавати - відняти!
Як я сам придумав це?
Запам’ятайте властивості логічних операторів. Працюйте з ними майже як додавання чи множення, якщо це допомагає. Незвично, що і (&), xor (^) і або (|) асоціативні, але вони є!
Запустіть наївну реалізацію спочатку, знайдіть шаблони у висновку, а потім починайте знаходити правила, які підтверджують, що шаблон є правдивим. Ще більше спростіть свою реалізацію та повторіть. Це, мабуть, маршрут, який пройшов оригінальний творець, підкреслений тим, що це не зовсім оптимально (тобто використовувати оператор перемикання, а не масив).