这段时间要沉迷刷题一段时间了,就让CSDN陪我一起吧!
一、题目大意
给定两个数字n和x,其中n是数组的长度,然后再给出n个数,是数组元素。规定每次操作可以将数组的其中一个元素a[i]用a[i]&x替换,求至少需要多少次操作,才能使数组中存在至少两个相同的元素?
二、题目思路以及AC代码
我真是没想到codeforce上也有题目这么坑的题。简直被坑惨,不同的理解完全不同的思路。
在这里我们需要好好的考虑以下这句话:
要注意这里的some i 指的是某个i的意思,而不是一些。
我一开始就是按照一些的思路去做的,当然思路也不难,我也很快写出来了,可就是WA,想了半天也没有想出为什么,最后看到别人的题解才发现,题目真坑啊!!!(一会下面我也贴一下我错误理解题目的代码,大家如果也做了的话可以对一下)
然后就是正确的题目了,正确题目的思路也不是很难,主要是需要想清楚一个问题,一个数与另一个数做按位与,做一次、两次、三次…的结果都是一样的,这个结论也很好理解。知道了这个结论之后,下面我们就很简单了,对于本题来说,就只需要考虑两个数组的问题,一个是原数组(记为a),一个是将原数组元素都和x进行与运算之后的数组(记为b)。
如果a数组中有相等的元素,那么不需要做操作就可满足条件,则输出0;
如果a数组中没有相等元素,b数组中也没有相等元素,因为再进行与运算也都和b数组一样,所以就说明无论操作多少次也都没有相等元素,那么输出-1;
如果a数组中没有相等元素,b数组中有相等元素,那么说明是存在的,下面就需要考虑是1次操作还是2次操作的问题:
对于1次操作,是a数组的某个元素与x做与操作之后正好等于a数组中的另一个元素。
对于2次操作,是a数组中的某个元素与x做与运算之后,等于a数组中的另一个元素和x做与运算。
基于以上的思路就可以写出代码了:
#include <iostream>
#define MAXN 100010
using namespace std;
int n, x;
int a[MAXN];
int b[MAXN];
int visa[MAXN];
int visb[MAXN];
int main()
{
cin >> n >> x;
bool flag = false;
bool flag1 = false;
for (int i = 0; i < n; i++) {
cin >> a[i];
b[i] = a[i] & x;
}
for (int i = 0; i < n; i++) {
if (visa[a[i]]) {
flag = true;
break;
}
visa[a[i]] = true;
}
if (flag) {
cout << 0 << endl;
}
else {
for (int i = 0; i < n; i++) {
if (visb[b[i]]) {
flag1 = true;
break;
}
visb[b[i]] = true;
}
if (!flag1) {
cout << -1 << endl;
}
else {
for (int i = 0; i < n; i++) {
if (visa[b[i]] && b[i] != a[i]) {
flag = true;
break;
}
}
if (flag)
cout << 1 << endl;
else
cout << 2 << endl;
}
}
return 0;
}
我原来那个错误理解的代码也不能白写,就也贴在下面吧,下面给出的是把some按照一些来理解的代码:
#include <iostream>
#define MAXN 100010
using namespace std;
int n, x;
int a[MAXN];
bool vis[MAXN];
void init() {
for (int i = 0; i < MAXN; i++) {
vis[i] = false;
}
}
int main() {
init();
cin >> n >> x;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
bool flag = true;
for (int i = 0; i < n; i++) {
if (vis[a[i]]) {
flag = false;
break;
}
vis[a[i]] = true;
}
if (!flag) {
cout << 0 << endl;
}
else {
int step = 0;
bool isFind = false;
do {
bool flag = false;
step++;
for (int i = 0; i < n; i++) {
int tmp = a[i] & x;
if (tmp == a[i]) continue;
flag = true;
if (vis[tmp]) {
isFind = true;
break;
}
vis[tmp] = true;
a[i] = tmp;
}
if (!flag) {
break;
}
} while (!isFind);
if (isFind) cout << step << endl;
else cout << -1 << endl;
}
return 0;
}
如果有问题,欢迎大家指正!!!