Автор проблеми: | Хасан Салех (MathModel) |
Підготовлено: | Хасан Салех (MathModel) |
Редагував: | Хасан Салех (MathModel) |
Рішення
Ми хочемо виразити число як XOR деяких "-спеціальних" чисел. -спеціальне число - це будь-яке число, бінарна форма якого має точно послідовних 's, а всі інші біти , тобто
для деякого зсуву t \ge 0. Іншими словами, воно переключає біти t, t+1, \dots, t+k-1 разом. Наша операція - XOR, тому переключення одного і того ж біта двічі скасовує.
Головне спостереження полягає в тому, що ця операція є односторонньою для бітів зліва направо (насправді з низу вгору). Подивіться на біти з найменш значущого біта вгору. Припустимо, що ми зараз на біті , і після всіх попередніх операцій біти 0,1,\dots,i-1 вже стали . Якщо біт є , нам не потрібно нічого робити. Якщо біт є , ми змушені використовувати -блок, який починається точно на :
будь-який блок, який починається після , не торкнеться біта взагалі,
будь-який блок, який починається до , торкнеться деякого біта і знову зламає те, що ми вже виправили,
тому єдиний законний спосіб очистити біт , не знищуючи менші біти, - це XOR
Після того, як ми це зробимо, біт стає , а біти i+1,\dots,i+k-1 переключаються; потім ми переходимо до наступного біта.
Отже, алгоритм буквально такий:
запишіть у двійковому вигляді (досить, щоб зберегти біт),
для i=0,1,2,\dots поки i+k \le 64:
якщо біт є , то візьміть блок, що починається на , додайте його до відповіді та XOR-те його в нашу робочу копію,
після того, як ми зробили всі можливі початки, якщо залишився будь-який у верхніх (k-1) бітах, то це неможливо (немає блоку, який може початися досить високо, щоб його покрити), тому відповідь - ,
в іншому випадку обрані блоки є точною однією дійсною конструкцією.
Чому це мінімально? Тому що щоразу, коли ми зустрічали , у нас не було вибору: цей повинен бути знищений прямо там. Тому будь-яке рішення повинно містити цей блок. Оскільки кожен обраний блок є примусовим, будь-яке рішення має однаковий мультисет блоків отже, цей жадібний алгоритм дає мінімальну кількість і є унікальним.
Формально, якщо ми позначимо b_i як поточне значення біта під час проходження, то для кожного з b_i=1 ми додаємо
до конструкції і робимо b_{i+j} \mathrel{\oplus}=1 для 0 \le j < k. В кінці, якщо деяке b_t=1 з t > 64-k, тоді ми виводимо .
Складність становить \mathcal{O}(\log^2 n).
def solve():
n,k=map(int,input().split())
b=n.bit_length()
a=[]
cur=0
for i in range(b):
bit=(n>>i)&1
x=bit^cur
a.append(x)
cur^=x
if i-k+1>=0:
cur^=a[i-k+1]
for j in range(1,k):
if b-j>=0 and a[b-j]:
print(-1)
return
base=(1<<k)-1
v=[base<<i for i,x in enumerate(a) if x]
print(len(v))
print(*v)
for _ in range(int(input())):
solve()