CF1427E. Xum

题目大意

初始集合里有一个奇数x,每次可以把集合的两个数相加/异或并把结果丢到集合里,构造方案使得有1

操作的数∈[0,5e18]

题解

好玩的题

如果搞出了y=2^k满足y>x,那么可以把x不断*2后和y消,每次往前吞一位,最后可以得到y/2

在y<x时要先消掉x前面的二进制1,如此往复可以得到1

问题变成构造y,如果x&2!=0就先把x变成x^2x

然后设z=x*2^k,并且z的最低位1刚好贴到x的最高位1,然后把(x+z)^x^z即可得到y

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
//#define file
using namespace std;

ll p[64],a[100001][3],x,y,z,s,tot;
int i,j,k,l;

void add(ll x,ll y,int tp) {++tot,a[tot][0]=x,a[tot][1]=y,a[tot][2]=tp;}

int main()
{
	#ifdef file
	freopen("CF1427E.in","r",stdin);
	#endif
	
	p[0]=1;
	fo(i,1,63) p[i]=p[i-1]*2;
	scanf("%lld",&x);if (x&2) add(x,x,0),add(x,x*2,1),x^=x*2;
	l=floor(log2(x));
	y=x;
	fo(i,1,l) add(y,y,0),y*=2;
	add(x,y,0),add(x+y,x,1),add((x+y)^x,y,1);
	s=(x+y)^x^y;
	y=x;
	while (y<s) y*=2;
	while (s>x)
	{
		z=y;
		while (z)
		{
			if (z&s) add(z,s,1),z^=s;
			add(z,z,0),z*=2;
		}
		s>>=1,y>>=1;
	}
	k=l;
	while (s>1)
	{
		z=x;
		fo(i,k,l)
		if (z&p[i])
		add(z,p[i],1),z^=p[i];
		while (z)
		{
			if (z&s) add(z,s,1),z^=s;
			add(z,z,0),z*=2;
		}
		s>>=1,--k;
	}
	
	printf("%d\n",tot);
	fo(i,1,tot)
	printf("%lld %c %lld\n",a[i][0],(!a[i][2])?'+':'^',a[i][1]);
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
posted @ 2020-10-12 22:53  gmh77  阅读(132)  评论(0编辑  收藏  举报