题目大意
初始集合里有一个奇数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
",tot);
fo(i,1,tot)
printf("%lld %c %lld
",a[i][0],(!a[i][2])?'+':'^',a[i][1]);
fclose(stdin);
fclose(stdout);
return 0;
}