#4508. Triples I

题目描述

已知 a a a,你可以选 m m m 个数,满足每个数均为 3 3 3 的倍数,且 m m m 个数的或为 a a a.

试最小化 m m m.

数据范围

100 % 100\% 100% 的数据, T ≤ 1 0 5 T\le 10^5 T105 a ≤ 1 0 18 a\le 10^{18} a1018.

题解

挺水的一题

如果 a a a 3 3 3 的倍数,则直接用 a a a 即可

否则考虑能否用两个 3 3 3 的倍数的数或起来为 a a a

a a a 拆位,显然 2 i % 3 = 1 / 2 2^i\%3=1/2 2i%3=1/2 ,所以把 % 3 \%3 %3 1 1 1 的和 % 3 \%3 %3 2 2 2 的位置分开,然后多的那一边拿出两个数相加,这样就可以放在另一边了,重复上述操作直到两边的差不超过 1 1 1 即可

代码

#include 
#define _(d) while(d(isdigit(c=getchar())))
typedef long long LL;using std::swap;
LL R(){char c;_(!);LL x=c^48;_()x=(x<<3)+(x<<1)+(c^48);return x;}
int T,t[2],m,u,v;LL a,p[2][65],x,y,j;
int main(){
	for (scanf("%d",&T);T--;){
		a=R();
		if (a%3==0){printf("1 %lld\n",a);continue;}
		j=1;t[0]=t[1]=0;
		for (int i=0;j<=a;i++,j<<=1)
			if (a&j) p[i&1][++t[i&1]]=j;
		u=0;v=1;if (t[0]>t[1]) swap(u,v);
		while(t[v]-t[u]>1)
			p[u][++t[u]]=p[v][t[v]]|p[v][t[v]-1],t[v]-=2;
		u=0;v=1;if (t[0]>t[1]) swap(u,v);
		x=0,y=0;for (int i=1;i<=t[u];i++)
			x|=(p[u][i]|p[v][i]),y|=(p[u][i]|p[v][i+1]);
		printf("2 %lld %lld\n",x,y);
	}
	return 0;
}

你可能感兴趣的:(#4508. Triples I)