牛客多校(第四场) D:triples I

链接:https://ac.nowcoder.com/acm/contest/884/D
来源:牛客网
 

题目描述

Doctor Elephant is testing his new program: output the bitwise or of the numbers inputed.

He has decided to input several multiples of 3 and the output of the program should be his favorite number aaa.

Because he is lazy, he decided to input as few numbers as possible. He wants you to construct such an input for every aaa he chose.

It's guaranteed that for every aaa in the input there is such a solution. If there're multiple solutions you can output any.

输入描述:

 

There're multiple test cases in a test file.

The first line contains a positive integer TTT - the number of test cases.

In each of the following TTT lines there is one positive integer aaa.

输出描述:

For each test case output a line. First you need to output the number of numbers in your input, and then you need to output these numbers, separating by spaces.

示例1

输入

复制

2
3
7

输出

复制

1 3
2 3 6

说明

3=3, (3|6)=7

备注:

1≤T≤1051 \leq T \leq 10^51≤T≤105, 1≤a≤10181 \leq a \leq 10^{18}1≤a≤1018.

 

分析:这题的意思就是给你一个数a,你要把它分解为多个能被3整除的数,使他们相 |(或) 后的结果为a。这一个二进制的问题。

1.当a为3的倍数只需要输出a即可。

2.当a不是3的倍数的时候:首先判断一个二进制数除以3余1还是2的问题,我们考虑二进制数每一位1(0不需要考虑),假如这个数最低位从0开始,就比如2^n,当n为偶数时,2^n%3=1,当n为奇数时,2^n%3=2;

这样我们就能够知道a包含几个数%3=1,几个数%3=2了(只需要看a为1的位置的奇数位个数和偶数位个数),

如43=101011:包含3个(100000,1000,10)%3=2,一个(1)%1=1。

接下来就可以开始怎么写代码了:

若a mod 3=1:
• 如果a中的二进制位有至少两个mod 3=1的,设它们为p和q,我们取{a-p,a-q}即可。
• 如果a中的二进制位有恰好一个mod 3=1的,那么设mod 3=1的这个位为p,mod 3=2
的某个位为q,我们取{a-p,p+q}即可。
• 如果a中的二进制位没有mod 3=1的,那么假设有三个mod 3=2的位p,q,r,我们取{ap-
q,p+q+r}即可。
• 若a mod 3=2只需把上面的讨论中1与2互换即可,是完全对称的。

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
const int M=1e5+5;
 
ll T,a,n;
vector<ll> p,p1,p2;
void dbnum(ll x){
    p.clear(); p1.clear(); p2.clear();
    while(x){
        p.pb(x&1);
        x>>=1;
    }
    n=p.size();
    for(ll i=0;i<n;i++)
        if(p[i]==1){
            if(i%2==0) p1.pb(1LL<<i);
            else p2.pb(1LL<<i);
        }      
}
int main(){
    scanf("%lld",&T);
    while(T--){
        scanf("%lld",&a);
        if(a%3==0){
            printf("1 %lld\n",a);
        }
        else{  
            dbnum(a);
            ll ans1,ans2;
            printf("2 ");
            if(a%3==1){
                if(p1.size()>=2){
                    ans1=a-p1[0];
                    ans2=a-p1[1];
                }
                else if(p1.size()==1){
                    //cout<<p1[0]<<" "<<p2[0];
                    ans1=a-p1[0];
                    ans2=p1[0]+p2[0];
                }
                else{
                    ans1=a-p2[0]-p2[1];
                    ans2=p2[0]+p2[1]+p2[2];
                }
            }
            else{
                if(p2.size()>=2){
                    ans1=a-p2[0];
                    ans2=a-p2[1];
                }
                else if(p2.size()==1){
                    ans1=a-p2[0];
                    ans2=p2[0]+p1[0];
                }
                else{
                    ans1=a-p1[0]-p1[1];
                    ans2=p1[0]+p1[1]+p1[2];
                }
            }
            if(ans1>ans2) swap(ans1,ans2);
            cout<<ans1<<" "<<ans2<<endl;
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值