#4508. Triples I

题目描述

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

试最小化 $m$.

数据范围

对 $100\%$ 的数据,$T\le 10^5$,$a\le 10^{18}$.

题解

挺水的一题

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

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

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

代码

#include <bits/stdc++.h>
#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;
}

猜你喜欢

转载自www.cnblogs.com/xjqxjq/p/11370163.html