2019牛客多校第四场D. triples I

题意

   给你一个n,问至少有几个数或运算起来可以等于n,并且输出数量和这个几个数(且这几个数是 3 的倍数)。题目说明给的n一定符合条件(不会输出n=1 之类不存在情况)。

题解

   题目说 n 一定符合条件,所以不考虑n==1 或 n == 4之类的数,此类数不符合条件

 

分类讨论

   当 n % 3 == 0 时,直接输出 n ,不用和其他数异或

 否则将n转换为二进制,因为二进制数 %3 的规律为  1 2 1 2 1 2 1 2

   当 n % 3 == 1时,

      ①当 二进制数位有 至少2 个 mod 3= 1,设为 p,q, 则两个数为   (n-p, n-q)

      ②当n中的二进制位恰好有一个 mod 3= 1,那么设mod 3 = 1 的这个位为p,mod 3 = 2的某个位为q,取(a-p, p+1)

      ③当n中的二进制没有 mod 3 = 1的,那么假设有三个mod = 2 的位p, q, r我们去(a-p-q, p+q+r);

  当n % 3 == 2 时,和n%3 == 1的情况相反

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
	int t;
	cin >> t;
	ll b[100];
	b[0] = 1;
	for(int i = 1; i <= 60; i++){      // 预处理2的指数,2的60次 > 10的18次
		b[i] = b[i-1] * 2;
	}
	while(t--){
		ll s, w, ans1, ans2;
		cin >> s;
		w = s;
		if(s % 3 == 0){                 // 当余3 == 0 时
			cout << 1 << " " << s << endl;
			continue;
		}
		ll a[100];
		int j = 60, a1 = 0, a2 = 0, c1[60], c2[60];
		memset(a, 0, sizeof(a));
		memset(c1, 0, sizeof(c1));memset(c2, 0, sizeof(c2));
		for(int i = 60; i >= 0; i--){ // 将数 转换为 二进制
			if(s - b[i] >= 0){
				a[j] = 1;
				if(j % 2 == 0){  // 二进制数 % 3 == 1的情况
					c1[a1] = j;
					a1++;
				}
				else{           // 二进制 % 3 == 2的情况
					c2[a2] = j; 
					a2++;
				}
				s = s - b[i];
			}	
			else{
				a[j] = 0;
			}
			j--;
		}
		/*for(int i = 0; i <= 10; i++){
			cout << a[i];
		}
		cout << endl<< a1 << " " << a2 << endl;*/
		if(w % 3 == 1){   // 输入的数 % 3 == 1
			if(a1 >= 2){    // 有至少两个二进制数位 % 3 == 1 (1 或4 或16 .... )
				ans1 = w - b[c1[0]];
				ans2 = w - b[c1[1]];
			}
			else if(a1 == 1){        // 正好一个
				ans1 = w - b[c1[0]];
				ans2 = b[c1[0]] + b[c2[0]];
			}
			else{           // 一个没有
				ans1 = w - b[c2[0]] - b[c2[1]];
				ans2 = b[c2[0]] + b[c2[1]] + b[c2[2]];
			}
		}
		else{             // %3 == 2
			if(a2 >= 2){
				ans1 = w - b[c2[0]];
				ans2 = w - b[c2[1]];
			}
			else if(a2 == 1){
				ans1 = w - b[c2[0]];
				ans2 = b[c2[0]] + b[c1[0]];
			}
			else{
				ans1 = w - b[c1[0]] - b[c1[1]];
				ans2 = b[c1[0]] + b[c1[1]] + b[c1[2]];
			}
		}
		cout << 2 << " " << ans1 << " " << ans2 << endl;
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值