Бінарні забави#12272

Бінарні забави (Розбір)

Автор проблеми:

Хасан Салех (MathModel)

Підготовлено:

Хасан Салех (MathModel)

Редагував:

Хасан Салех (MathModel)

Рішення

Ми хочемо виразити число як XOR деяких "-спеціальних" чисел. -спеціальне число - це будь-яке число, бінарна форма якого має точно послідовних 's, а всі інші біти , тобто

x = \bigl((1 \ll k) - 1\bigr) \ll t

для деякого зсуву t \ge 0. Іншими словами, воно переключає біти t, t+1, \dots, t+k-1 разом. Наша операція - XOR, тому переключення одного і того ж біта двічі скасовує.

Головне спостереження полягає в тому, що ця операція є односторонньою для бітів зліва направо (насправді з низу вгору). Подивіться на біти з найменш значущого біта вгору. Припустимо, що ми зараз на біті , і після всіх попередніх операцій біти 0,1,\dots,i-1 вже стали . Якщо біт є , нам не потрібно нічого робити. Якщо біт є , ми змушені використовувати -блок, який починається точно на :

  • будь-який блок, який починається після , не торкнеться біта взагалі,

  • будь-який блок, який починається до , торкнеться деякого біта і знову зламає те, що ми вже виправили,

тому єдиний законний спосіб очистити біт , не знищуючи менші біти, - це XOR

\bigl((1 \ll k) - 1\bigr) \ll i.

Після того, як ми це зробимо, біт стає , а біти i+1,\dots,i+k-1 переключаються; потім ми переходимо до наступного біта.

Отже, алгоритм буквально такий:

  1. запишіть у двійковому вигляді (досить, щоб зберегти біт),

  2. для i=0,1,2,\dots поки i+k \le 64:

    • якщо біт є , то візьміть блок, що починається на , додайте його до відповіді та XOR-те його в нашу робочу копію,

  3. після того, як ми зробили всі можливі початки, якщо залишився будь-який у верхніх (k-1) бітах, то це неможливо (немає блоку, який може початися досить високо, щоб його покрити), тому відповідь - ,

  4. в іншому випадку обрані блоки є точною однією дійсною конструкцією.

Чому це мінімально? Тому що щоразу, коли ми зустрічали , у нас не було вибору: цей повинен бути знищений прямо там. Тому будь-яке рішення повинно містити цей блок. Оскільки кожен обраний блок є примусовим, будь-яке рішення має однаковий мультисет блоків отже, цей жадібний алгоритм дає мінімальну кількість і є унікальним.

Формально, якщо ми позначимо b_i як поточне значення біта під час проходження, то для кожного з b_i=1 ми додаємо

x_i = \bigl((1 \ll k) - 1\bigr) \ll i

до конструкції і робимо 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()