QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#72187#4820. Kitten's ComputerQingyuAC ✓2ms3532kbC++234.2kb2023-01-14 22:52:262023-01-14 22:52:28

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-01-14 22:52:28]
  • 评测
  • 测评结果:AC
  • 用时:2ms
  • 内存:3532kb
  • [2023-01-14 22:52:26]
  • 提交

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;
}
// 5->3, depth = {a: 3, b: 5, c: 6}
void compress(Register &a, Register &b, Register &c, Register &d, Register &f) {
	full_adder_ex(a, b, c);
	Register e=d&f;
	d^=f;
	c=Register(c&d)^Register(b&e);
	b=Register(b^e)^Register(a&d);
	a^=d;
	b<<=1;
	c<<=2;
}
// 6->3, depth = {a: 3, b: 6, c: 6}
void compress(Register &a, Register &b, Register &c, Register &d, Register &e, Register &f) {
	full_adder_ex(a, b, c);
	full_adder_ex(d, e, f);
	c=Register(Register(a&f)^Register(c&d))^Register(b&e);
	b=Register(b^e)^Register(a&d);
	a^=d;
	b<<=1;
	c<<=2;
}
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;
	int caseId=3;
	if(caseId==1) {
		Register a[4];
		for(int i=1; i<=3; ++i) a[i]=~a[0], a[i]>>=64-i;
		a[1]<<=1;
		a[2]<<=9;
		a[3]<<=3;
		a[0]=Register(a[1]|a[2])|a[3];
	}
	if(caseId==2) {
		Register a, b;
		a+=b;
	}
	if(caseId==3) {
		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];
		}
		int n=64;
		while(n>2) {/*
			for(; n-l>=6; n-=3, l+=3)
				compress(*part[l], *part[l+1], *part[l+2], *part[n-3], *part[n-2], *part[n-1]);
			if(n-l==5) {
				compress(*part[l], *part[l+1], *part[l+2], *part[n-2], *part[n-1]);
				l+=3;
				n-=2;
			}*/
			for(re int i=0;i<n;i++)pp[i]=i;
			std::sort(pp,pp+n,cmp);
			compress(*part[pp[0]], *part[pp[1]], *part[pp[2]]);
			--n;
			re int tt=std::max(std::max(tm[pp[0]],tm[pp[1]]),tm[pp[2]]);
			tm[pp[0]]=tt+2;
			tm[pp[1]]=tt+4;
			std::swap(tm[pp[2]],tm[n]);
			std::swap(*part[pp[2]],*part[n]);
		}
		*part[0]+=*part[1];
	}
	return 0;
}


详细

Test #1:

score: 100
Accepted
time: 2ms
memory: 3532kb

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=63