速通ACM省铜第十九天 赋源码(SUMdamental Decomposition)

引言:

        我们今天来讲一道CF评级为1300的题,这题虽然评为1300,但需要注意的细节还是比较多的

        那么接下来,就进入今天的题目讲解啦——————————————>

                                

SUMdamental Decomposition

        按照惯例,我们先看题目

        题意分析

        题目链接在这里Problem - 2108B - Codeforces

        不想跳转的可看下图

        题目意思很简单,就是给你俩个数,第一个数代表的是要用到几个数字,第二个数代表的是将这几个数字全部异或得到的值

        然后题目问你满足条件的数字和加起来最少是多少,然后输出即可

        题目意思很简单,那么我们进入代码的逻辑梳理环节


        逻辑梳理

        首先,我们先找出不可能实现的情况,首先想到的就是个数为1,要达到0的情况,这是不可能的,因为数的要求是>0,那么1,0这种情况就肯定会是-1了,那么还有别的情况会输出-1吗,我们来细细想想

        除开1,0这种特殊情况外,还有三种情况

        第一种(个数为1,要得到的值不为0的情况)

                很明显,这种都是成立的

        第二种(个数不为1,要得到的值为0的情况)

                很明显,这种也是明显成立的,我们假设为偶数和奇数的情况

                偶数时候,只要全为1就好了

                奇数时候,只需要有2个元素为3,2就好啦,其余都为1就可以了,为什么呢,因为32异或完就是1了,这个时候相当于偶数个1异或,然后最后得到的肯定就是0了

                这种情况也是后面代码实现需要特判的点

        第三种(个数不为1,要得到的值也不为0的情况)

                这种情况我们就可以先将需要得到的值转换为二进制,然后如果个数<=二进制中1的个数时,直接输出要得到的值就可以了,这个应该还是很明了的

                那么如果个数比二进制中1的个数多的时候,这个时候我们就可以来分情况来进行讨论了

                首先是剩余的个数为奇数的情况

                这个情况只需要再加上剩余的个数然后再加上1就可以了,为什么呢,因为可以在前面的操作时候让0位变成与要求的数字相反的数字就可以了,这种操作会让前面操作时候多花1点,之后只需要全用1就可以了,就能得到需要得到的数了,那么我们来看另一种情况

                剩余的个数为偶数的情况

                这个就很简单了,只需要加上剩余的个数就可以了,因为剩余的偶数全选1,这样最终得到的元素也不会变化

        这三种情况都分析完啦,但是第三种情况有一个需要特别注意,就是如果需要得到的数是1的时候,那么就无法调整了,所以这种情况需要再特判一下,这个题的所有情况就全都齐全了

        那么,所有情况都分析完啦,接下来我们进入代码的实现环节


        代码实现

        具体代码实现其实就很简单了,这里就直接放AC码啦

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <queue>
#include <vector>
using namespace std;

int t;

void solve()
{
	long long n, x;
	cin >> n >> x;
	long long ans = 0;
	if (n == 1 && x == 0)
		cout << "-1" << endl;
	else
	{
		if (x == 1)
		{
			if (n % 2)
				cout << n << endl;
			else
				cout << 5 + n - 2 << endl;
			return;
		}
		if (x == 0)
		{
			if (n % 2)
			{
				cout << 6 + n - 3 << endl;
			}
			else
			{
				cout << n << endl;
			}
			return;
		}
		int chang = 0;
		int weimin = 0;
		long long X = x;
		for (int i = 50; i >= 0; i--)
		{
			if (pow(2, i) <= X)
			{
				X -= pow(2, i);
				weimin = i;
				chang++;
			}
		}
		if (n <= chang)
		{
			cout << x << endl;
			return;
		}
		if ((n - chang) % 2)
		{
				cout << x + n - chang + 1 << endl;
			return;
		}
		cout << x + n - chang << endl;
	}
}

int main()
{
	cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}

          那么,这题就讲解完啦

结语:

        今日算法讲解到此结束啦,希望对你们有所帮助,谢谢观看,如果觉得不错可以分享给朋友哟。有什么看不懂的可以评论问哦

 

评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值