답안 #798194

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
798194 2023-07-30T13:08:40 Z finn__ 레지스터 (IOI21_registers) C++17
100 / 100
2 ms 628 KB
#include "registers.h"
#include <vector>
#include <iostream>

constexpr size_t B = 2000;
constexpr int ONE = 50, ALL_ONES = 51, MASK = 52, K_MASK = 53, ALL_ZEROS = 54;

void construct_instructions(int s, int n, int k, int q)
{
    if (k <= 2)
    {
        // Store a in r0 and b in r1
        std::vector<bool> bits(2000);
        for (size_t i = 0; i < k; ++i)
            bits[i] = 1;
        append_store(11, bits);
        append_move(1, 0);
        append_and(1, 1, 11);
        append_right(0, 0, k);

        if (k == 1)
        {
            append_and(0, 0, 1);
        }
        else
        {
            append_or(2, 0, 1);    // r2 = a or b
            append_xor(3, 0, 1);   // r3 = a xor b
            append_and(2, 2, 3);   // r2 = (a or b) and (a xor b)
            append_right(3, 2, 1); // r3 = (a or b) and (a xor b) right shifted by 1
            append_and(2, 2, 3);   // r2 = first criterion to add 1

            append_right(4, 0, 1);
            append_and(4, 4, 1);
            append_right(5, 1, 1);
            append_and(5, 5, 0);
            append_or(4, 4, 5); // r4 = second criterion to add 1

            append_and(2, 2, 4); // r2 = the stuff to be added
            append_and(0, 1, 0);
            append_add(0, 0, 2);
        }
        return;
    }
    std::vector<bool> r(B);
    r[0] = 1;
    append_store(ONE, r);
    fill(r.begin() + 1, r.end(), 1);
    append_store(ALL_ONES, r);
    fill(r.begin(), r.end(), 0);
    for (int i = k; i < B; i += k)
        r[i] = 1;
    append_store(MASK, r);
    fill(r.begin() + k, r.end(), 0);
    fill(r.begin(), r.begin() + k, 1);
    append_store(K_MASK, r);
    fill(r.begin(), r.end(), 0);
    append_store(ALL_ZEROS, r);

    // writes min in a, max in b
    auto append_swap = [&](int a, int b)
    {
        append_not(40, a);
        append_add(40, 40, ONE);
        append_add(40, 40, b); // 40 : b - a

        append_xor(41, 40, a);
        append_xor(41, 41, b); // 41 : (b - a) ^ a ^ b
        append_and(40, 41, MASK);
        append_right(41, 40, k);
        append_not(41, 41);
        append_add(41, 41, ONE);
        append_add(42, 40, 41); // 42 : 1-mask if a > b, else 0-mask

        append_xor(43, a, b);
        append_and(43, 43, 42); // 43 : a_i ^ b_i if a_i > b_i
        append_xor(a, a, 43);   // a_i = min(a_i, b_i)
        append_xor(b, b, 43);   // b_i = max(a_i, b_I)
    };

    if (!s)
    {
        int l = 64;
        append_left(2, ALL_ONES, n * k);
        append_or(0, 0, 2);
        append_move(1, 0);
        append_right(0, 0, l * k); // 0 : upper half
        append_left(2, ALL_ONES, l * k);
        append_or(1, 1, 2); // 1 : lower half
        append_print(0);
        append_print(1);

        while (l)
        {
            append_swap(0, 1);
            l >>= 1;
            append_move(1, 0);
            append_right(0, 0, l * k);
            append_left(2, ALL_ONES, l * k);
            append_or(1, 1, 2);
            append_print(0);
            append_print(1);
        }
    }
    else
    {
        for (int i = 0; i < n; ++i)
        {
            if (!(i & 1))
            {
                append_right(10, 0, (i - i / 2) * k);
                append_left(11, K_MASK, (i / 2) * k);
                append_and(10, 10, 11);
                append_or(2, 2, 10);
            }
            else
            {
                append_right(10, 0, (i - i / 2) * k);
                append_left(11, K_MASK, (i / 2) * k);
                append_and(10, 10, 11);
                append_or(3, 3, 10);
            }
        }

        append_print(2);
        append_print(3);

        append_left(10, ALL_ONES, ((n + 1) / 2) * k);
        append_or(2, 2, 10);
        append_left(10, ALL_ONES, (n / 2) * k);
        append_or(3, 3, 10);

        append_print(2);
        append_print(3);

        for (int j = 0; j < 2 * n - 2; ++j)
        {
            if (!(j & 1))
            {
                append_swap(2, 3);
            }
            else
            {
                append_right(4, 2, k);
                append_swap(3, 4);
                append_left(5, 4, k);
                append_and(4, 2, K_MASK);
                append_or(2, 4, 5);
            }

            append_print(2);
            append_print(3);
        }

        append_move(0, ALL_ZEROS);
        for (int i = 0; i < n; ++i)
        {
            if (!(i & 1))
            {
                append_left(10, 2, (i - i / 2) * k);
                append_left(11, K_MASK, i * k);
                append_and(10, 10, 11);
                append_or(0, 0, 10);
            }
            else
            {
                append_left(10, 3, (i - i / 2) * k);
                append_left(11, K_MASK, i * k);
                append_and(10, 10, 11);
                append_or(0, 0, 10);
            }
        }
    }
}

Compilation message

registers.cpp: In function 'void construct_instructions(int, int, int, int)':
registers.cpp:14:30: warning: comparison of integer expressions of different signedness: 'size_t' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
   14 |         for (size_t i = 0; i < k; ++i)
      |                            ~~^~~
registers.cpp:51:23: warning: comparison of integer expressions of different signedness: 'int' and 'const size_t' {aka 'const long unsigned int'} [-Wsign-compare]
   51 |     for (int i = k; i < B; i += k)
      |                     ~~^~~
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 1 ms 304 KB Output is correct
3 Correct 1 ms 212 KB Output is correct
4 Correct 1 ms 212 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 1 ms 212 KB Output is correct
3 Correct 1 ms 212 KB Output is correct
4 Correct 1 ms 212 KB Output is correct
5 Correct 1 ms 212 KB Output is correct
6 Correct 1 ms 212 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 340 KB Output is correct
2 Correct 1 ms 300 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 340 KB Output is correct
2 Correct 1 ms 300 KB Output is correct
3 Correct 2 ms 628 KB Output is correct
4 Correct 2 ms 628 KB Output is correct
5 Correct 1 ms 596 KB Output is correct
6 Correct 1 ms 596 KB Output is correct
7 Correct 1 ms 596 KB Output is correct