速通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;elsecout << 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;
}
那么,这题就讲解完啦
结语:
今日算法讲解到此结束啦,希望对你们有所帮助,谢谢观看,如果觉得不错可以分享给朋友哟。有什么看不懂的可以评论问哦