triples 1

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

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld

题目描述

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

题意:

给一个T,下面给T个数a

将a分解成多个数b1~bn(bi为3的倍数),b1 | b2 | …… | bn = a

输出n和bi

思路:

分类讨论。

• 一个二进制位mod 3只可能是1或者2。

• 如果a是3的倍数,那么我们直接取{a}即可。

• 否则如果a的二进制位只有一位或两位(指的是a的二进制有几个1),我们根本取不出0以外的三的倍数,所以无解。

• 接下来考虑a至少有三位的情况。

• 若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,我们取{a- p-q,p+q+r}即可。

• 若a mod 3=2只需把上面的讨论中1与2互换即可,是完全对称的。

PS:预先在向量bb里面存(1LL<<i),可节省点时间,而且千万别用pow函数,同学就是因为pow WA了好多次

标程:

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
#define pb push_back
int T; ll a,x,y;
void sol()
{
	scanf("%lld",&a);
	vector<ll> bb[2];
	for(int i=0;i<=60;++i)
		if((a>>i)&1) bb[i&1].pb(1LL<<i);
	if(a%3==0) printf("1 %lld\n",a);
	else if(bb[0].size()+bb[1].size()<=2) for(;;);
	else
	{
		int s=(a%3==2);
		if(bb[s].size())
		{
			x=a-bb[s][0];
			if(bb[!s].size()) y=bb[s][0]+bb[!s][0];
			else y=a-bb[s][1];
		}
		else x=a-bb[!s][0]-bb[!s][1],
		y=bb[!s][0]+bb[!s][1]+bb[!s][2];
		printf("2 %lld %lld\n",y,x);
	}
}
int main()
{
	scanf("%d",&T);
	while(T--) sol();
}

我按思路改的标程:

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
#define pb push_back
int T; ll a,x,y;
void sol()
{
	scanf("%lld",&a);
	vector<ll> bb[2];
	for(int i=0;i<=60;++i)
		if((a>>i)&1) bb[i&1].pb(1LL<<i);
	if(a%3==0) printf("1 %lld\n",a);
	else if(bb[0].size()+bb[1].size()<=2) for(;;);
	else
	{
		ll ans1,ans2;
		int s=a%3;
		if(s==1){
			if(bb[0].size()>=2){
				ans1=a-bb[0][0];
				ans2=a-bb[0][1];
			}
			else if(bb[0].size()==1){
				ans1=a-bb[0][0];
				ans2=bb[0][0]+bb[1][0];
			}
			else{
				ans1=a-bb[1][0]-bb[1][1];
				ans2=bb[1][0]+bb[1][1]+bb[1][2];
			}
		}
		else{
			if(bb[1].size()>=2){
				ans1=a-bb[1][0];
				ans2=a-bb[1][1];
			}
			else if(bb[1].size()==1){
				ans1=a-bb[1][0];
				ans2=bb[1][0]+bb[0][0];
			}
			else{
				ans1=a-bb[0][0]-bb[0][1];
				ans2=bb[0][0]+bb[0][1]+bb[0][2];
			}
		}
		if(ans1>ans2){
			swap(ans1,ans2);
		}
		printf("2 %lld %lld\n",ans1,ans2);
	}
}
int main()
{
	scanf("%d",&T);
	while(T--) sol();
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值