QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#72198 | #4820. Kitten's Computer | Qingyu | AC ✓ | 5ms | 3644kb | C++23 | 3.3kb | 2023-01-14 23:52:21 | 2023-01-14 23:52:22 |
Judging History
answer
#include <bits/stdc++.h>
#define meow(args...) fprintf(stderr, args)
char name[][4]={"", "XOR", "AND", "OR"};
int queue[65536];
unsigned short ql, qr;
struct Sentence {
int op, j, k;
};
struct Register {
int i;
Register() {
assert(ql!=qr);
i=queue[ql++];
}
Register(const Register &o) {
assert(ql!=qr);
i=queue[ql++];
*this=o;
}
Register(const Sentence &o) {
assert(ql!=qr);
i=queue[ql++];
*this=o;
}
~Register() {
queue[qr++]=i;
}
Register &operator=(const Register &o) {
printf("SET %d %d\n", i, o.i);
return *this;
}
Register &operator=(const Sentence &o) {
if(o.op)
printf("%s %d %d %d\n", name[o.op], i, o.j, o.k);
else
printf("NOT %d %d\n", i, o.j);
return *this;
}
Register &operator<<=(int x) {
if(x) printf("LSH %d %d\n", i, x);
return *this;
}
Register &operator>>=(int x) {
if(x) printf("RSH %d %d\n", i, x);
return *this;
}
Sentence operator^(const Register &o) const {return {1, i, o.i};}
Sentence operator&(const Register &o) const {return {2, i, o.i};}
Sentence operator|(const Register &o) const {return {3, i, o.i};}
Sentence operator~() {return {0, i};}
Register &operator^=(const Register &o) {return *this = *this ^ o;}
Register &operator&=(const Register &o) {return *this = *this & o;}
Register &operator|=(const Register &o) {return *this = *this | o;}
// Register operator<<(int x) const {return Register(*this)<<=x;}
// Register operator>>(int x) const {return Register(*this)>>=x;}
};
Register &operator+=(Register &a, const Register &b) {
Register propagate[64], generate[64];
for(int i=0; i<64; ++i) {
propagate[i]=a^b;
propagate[i]<<=i;
generate[i]=a&b;
generate[i]<<=i;
}
for(int i=1; i<64; i*=2) {
for(int j=0; j<64-i; ++j) {
generate[j]|=Register(propagate[j]&generate[j+i]);
propagate[j]&=propagate[j+i];
}
}
a=Register(a^b)^generate[1];
return a;
}
// depth = {a: 2, b: 3, c: 2}
void full_adder_ex(Register &a, Register &b, Register &c) {
Register x=b&c, y=b^c;
//c=a&x;
b=Register(a&y)^x;
a^=y;
}
// 3->2, depth = {a: 2, b: 4}
void compress(Register &a, Register &b, Register &c) {
full_adder_ex(a, b, c);
b<<=1;
}
int tm[1010],pp[1010];
#define re register
inline bool cmp(re int a,re int b){return tm[a]<tm[b];}
int main() {
for(int i=1; i<=400; ++i) queue[qr++]=i;
Register a, b, *part[64]={&a};
for(int i=1; i<64; ++i) {
part[i]=new Register;
*part[i]=a;
*part[i]<<=i;
}
for(int i=0; i<64; ++i) {
Register filter[64];
for(int j=0; j<64; ++j) {
filter[j]=b;
filter[j]<<=63-i;
filter[j]>>=63;
filter[j]<<=j;
}
for(int j=1; j<64; j*=2) {
for(int k=0; k<64; k+=2*j) filter[k]|=filter[j+k];
}
*part[i]&=filter[0];
}
auto merge=[&](int i, int j, int k) {
compress(*part[i], *part[j], *part[k]);
re int tt=std::max(std::max(tm[i],tm[j]),tm[k]);
tm[i]=tt+2;
tm[j]=tt+4;
};
int n=64;
for (int i=0;i<21;++i){
fprintf(stderr,"merge %d %d %d\n",2*i,2*i+1,63-i);
merge(2*i,2*i+1,63-i);
}
n=43;
for (int i=0;i<14;++i){
merge(2*i,2*i+1,42-i);
}
n=29;
while(n>2) {
for(re int i=0;i<n;i++)pp[i]=i;
std::sort(pp,pp+n,cmp);
merge(pp[0], pp[1], pp[2]);
--n;
std::swap(tm[pp[2]],tm[n]);
std::swap(*part[pp[2]],*part[n]);
}
*part[0]+=*part[1];
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 5ms
memory: 3644kb
input:
main
output:
SET 3 1 LSH 3 1 SET 4 1 LSH 4 2 SET 5 1 LSH 5 3 SET 6 1 LSH 6 4 SET 7 1 LSH 7 5 SET 8 1 LSH 8 6 SET 9 1 LSH 9 7 SET 10 1 LSH 10 8 SET 11 1 LSH 11 9 SET 12 1 LSH 12 10 SET 13 1 LSH 13 11 SET 14 1 LSH 14 12 SET 15 1 LSH 15 13 SET 16 1 LSH 16 14 SET 17 1 LSH 17 15 SET 18 1 LSH 18 16 SET 19 1 LSH 19 17 ...
result:
ok Correct: depth=64