답안 #1107052

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
1107052 2024-10-31T13:11:45 Z azberjibiou 레지스터 (IOI21_registers) C++17
100 / 100
4 ms 1212 KB
#include "registers.h"
#include <bits/stdc++.h>
using namespace std;
/*
bool secret[100][2000];
void append_move(int t, int y){for(int i=0;i<2000;i++) secret[t][i]=secret[y][i];}
void append_store(int idx, vector <bool> v){ for(int i=0;i<2000;i++) secret[idx][i]=v[i];}
void append_and(int t, int a, int b){for(int i=0;i<2000;i++) secret[t][i]=(secret[a][i]&secret[b][i]);}
void append_or(int t, int a, int b){for(int i=0;i<2000;i++) secret[t][i]=(secret[a][i]|secret[b][i]);}
void append_not(int t, int y){for(int i=0;i<2000;i++) secret[t][i]=(!secret[y][i]);}
void append_xor(int t, int a, int b){for(int i=0;i<2000;i++) secret[t][i]=secret[a][i]^secret[b][i];}
void append_left(int t, int y, int k){
    vector <bool> tmp(2000, false);
    for(int i=0;i<2000;i++) tmp[i]=(i<k ? false : secret[y][i-k]);
    for(int i=0;i<2000;i++) secret[t][i]=tmp[i];
}
void append_right(int t, int y, int k){for(int i=0;i<2000;i++) secret[t][i]=(i+k>=2000 ? false : secret[y][i+k]);}
void append_add(int t, int a, int b){
    vector <bool> tmp(2000, false);
    for(int i=0;i<2000;i++){
        int nv=(int)secret[a][i]+(int)secret[b][i]+(int)tmp[i];
        tmp[i]=nv%2;
        if(i!=2000) tmp[i+1]=nv/2;
    }
    for(int i=0;i<2000;i++) secret[t][i]=tmp[i];
}
void print(int t){
    printf("%2d: ", t);
    for(int i=0;i<32;i++) printf("%d", secret[t][i]);
    printf("\n");
}
*/
void print(int t){}
void solv0(int n, int k ,int q){
    int bit;
    if(n==2) bit=1;
    else bit=7;
    int tot=(1<<bit);
    // set 1 for a[n+1]~a[2^bit-1]
    vector <bool> v0(2000, false);
    for(int i=n*k;i<tot*k;i++) v0[i]=true;
    if(n!=tot){
        append_store(50, v0);
        append_or(0, 0, 50);
    }
    for(int i=0;i<bit;i++){
        vector <bool> v1(2000, false), v2(2000, false);
        for(int j=0;j<tot;j++){
            if(j%(1<<(i+1))==0){
                for(int z=j*k;z<(j+1)*k;z++) v1[z]=true;
            }
            else if(j%(1<<i)==0){
                for(int z=j*k;z<(j+1)*k;z++) v2[z]=true;
            }
        }
        // 1: 2^(i+1)x번째 값, 2: 2^(i+1)x+2^i번째 값
        append_store(51, v1);
        append_store(52, v2);
        append_move(1, 0);
        append_move(2, 0);
        append_and(1, 1, 51);
        append_and(2, 2, 52);
        append_right(2, 2, (1<<i)*k);
        // 3: !2, 4: 1+3의 k+1번째 자리
        //!y = 2^b-1 - y
        // x + !y < 2^b <=> x+2^b-1-y < 2^b <=> x-y-1<0 <=> x<=y
        // k+1번째 자리가 0 <=> x<=y
        append_not(3, 2);
        append_and(3, 3, 51);
        append_add(4, 1, 3);
        vector <bool> v3(2000, false);
        for(int j=0;j<tot;j++){
            if(j%(1<<(i+1))==0) v3[(j+1)*k]=true;
        }
        append_store(53, v3);
        append_and(4, 4, 53);
        append_right(4, 4, k);
        //5: 0 -> 1111, 1 -> 0000, 6: !5
        append_add(5, 4, 51);
        append_and(5, 5, 51);
        append_not(6, 5);
        append_and(6, 6, 51);
        //0: 5&1+6&2
        append_and(7, 5, 1);
        append_and(8, 6, 2);
        append_add(0, 7, 8);
    }
}
void solv1(int n, int k, int q){
    vector <bool> v0(2000, false);
    for(int i=0;i<2*n;i++) if(i%2==1) for(int j=i*k;j<(i+1)*k;j++) v0[j]=true;
    append_store(50, v0);
    //make space between elements
    append_and(1, 0, 50);
    append_xor(0, 0, 1);
    print(0);
    print(1);
    int del=(n%2==0 ? n-1 : n);
    append_left(1, 1, del*k);
    print(1);
    append_or(0, 0, 1);
 
    //99: ans
    append_left(99, 0, 2000-k);
    append_right(99, 99, 2000-k);
    print(0);
    //53: 0~i번째 원소 자리의 k번째 자리만 true, 밖으로 빼내도 됨
    vector <bool> v3(2000, false);
    for(int j=0;j<n;j++) v3[(2*j+1)*k]=true;
    append_store(53, v3);
    for(int i=1;i<n;i++){
        print(99);
        // 51: i번째 원소 자리만 true
        vector <bool> v1(2000, false);
        for(int j=2*i*k;j<(2*i+1)*k;j++) v1[j]=true;
        append_store(51, v1);
        //52: 0~i번째 원소 자리만 true
        vector <bool> v2(2000, false);
        for(int j=0;j<=i;j++) for(int z=2*j*k;z<(2*j+1)*k;z++) v2[z]=true;
        append_store(52, v2);
        //2: ai를 0~i까지 복사
        append_and(2, 0, 51);
        int pos=i, b=0;
        while(pos>0){
            append_right(3, 2, 2*(1<<b)*k);
            append_or(2, 2, 3);
            pos-=(1<<b);
            b++;
        }
        //4: 0~i-1까지 정렬된 aj + ai
        append_and(4, 0, 51);
        append_or(4, 4, 99);
        //5: !4
        append_not(5, 4);
        append_and(5, 52, 5);
        //6: !4+2
        append_add(6, 5, 2);
        print(6);
        //7: 덧셈의 결과 자리를 일의 자리로 옮기기
        //ai+!aj>=2^k => aj<ai => 7=1 => 8=0
        append_and(7, 6, 53);
        append_right(7, 7, k);
        print(7);
        //8: (!7)로 0~k-1번째 자리 채우기
        append_add(8, 7, 52);
        //9: 8을 오른쪽으로 1칸 시프트
        append_left(9, 8, 2*k);
        //10: 4를 오른쪽으로 1칸 시프트
        append_left(10, 4, 2*k);
 
        /* 중간 정리
        2: ai 복사본
        4. 0~i-1까지 정렬된 aj + ai
        10. 1칸 시프트된 4
        (8, 9)=
        (0, 0) => aj
        (1, 0) => ai
        (1, 1) => a_{j-1}
        want: !1&aj+1&(!2&ai+2&a{j-1})
        */
 
        print(2);
        print(4);
        print(10);
        print(8);
        print(9);
 
        //11: !8
        append_not(11, 8);
        append_and(11, 52, 11);
        //12: !9
        append_not(12, 9);
        append_and(12, 52, 12);
        //99: 11&4+8&(12&2+9&10)
        append_and(13, 11, 4);
        append_and(14, 12, 2);
        append_and(15, 9, 10);
        append_add(16, 14, 15);
        append_and(17, 8, 16);
        append_add(99, 13, 17);
        print(13);
        print(17);
 
    }
    print(99);
    //remove space between elements
    for(int i=1;i<n;i++){
        append_right(98, 99, i*k);
        append_left(98, 98, (i-1)*k);
        append_left(97, 99, 2000-i*k);
        append_right(97, 97, 2000-i*k);
        append_or(99, 98, 97);
    }
    append_move(0, 99);
}
void construct_instructions(int s, int n, int k, int q) {
    if(s==0){
        solv0(n, k, q);
    }
    else{
        solv1(n, k, q);
    }
}
/*
int main(){
    secret[0][0]=secret[0][1]=secret[0][2]=secret[0][3]=true;
    //secret[0]={true, true, true, false, false, true, false, false};
    construct_instructions(1, 4, 2, 1557);
    for(int i=0;i<8;i++) printf("%d", secret[0][i]);
}
*/
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 336 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 336 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 336 KB Output is correct
2 Correct 1 ms 336 KB Output is correct
3 Correct 1 ms 336 KB Output is correct
4 Correct 1 ms 504 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 336 KB Output is correct
2 Correct 1 ms 508 KB Output is correct
3 Correct 1 ms 336 KB Output is correct
4 Correct 1 ms 604 KB Output is correct
5 Correct 1 ms 336 KB Output is correct
6 Correct 1 ms 336 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 508 KB Output is correct
2 Correct 1 ms 336 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 508 KB Output is correct
2 Correct 1 ms 336 KB Output is correct
3 Correct 4 ms 1212 KB Output is correct
4 Correct 3 ms 1184 KB Output is correct
5 Correct 2 ms 784 KB Output is correct
6 Correct 2 ms 784 KB Output is correct
7 Correct 4 ms 784 KB Output is correct