算法思维训练之MEX和构造实战演练 (2月6日)

121 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情

Mikasa(求mex)

题意:找到最小的非负整数x且保证x不在 n0,n1,,nmn⊕0,n⊕1,…,n⊕m 中。

在这m+1个数中,没有出现过最小的非负整数,

nk=xn^k=x,且km+1k ≥ m+1

也可以转换成 nx=km+1n^x=k ≥ m+1

则本题等价于:

找到一个最小的数x,使得n^x ≥ m+1$

题解:

① n > m,x=0即可满足题意

② n ≤ m时:

令 m+1 = t

将n和t诸位进行分类讨论:

从高位往低位枚举二进制的 n 和 t 的每一位

(1) 如果当前位一直满足 ni==tin_i == t_i,那么k=0即可

(2) 如果存在某一位有:ni=1,ti=0n_i = 1, t_i = 0,那么ki=0k_i = 0;

(3) 如果存在某一位有:ni=0,ti=1n_i = 0, t_i = 1,那么ki=1k_i = 1;

存一个变量k,将枚举每一位的结果加入k和n,n跟m比较,如果n>m就不用再比了。

Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int qmi(int a, int k) { int res = 1; while (k) { if (k & 1) res = res * a; k >>= 1; a = a * a; } return res;
}
signed main() {
	int _;
	cin >> _;
	while (_--) {
	    int n, m;
	    cin >> n >> m;
	    if (n > m) {cout << 0 << endl; continue; }
	    int k = 0;
	    for (int i = 30; i >= 0; i--) {
	        int a = n >> i & 1, b = (m + 1) >> i & 1;
	        if (a == b) continue;
	        if (b) {
	            k += qmi(2, i);//存k
	            n += qmi(2, i);//改n
	        }
	        if (n > m) break;
	    }
	    cout << k << endl;
	}
	return 0;
}

这道题我用快速幂,没别的意思,就是单纯不喜欢位运算而已,还有一种位运算的解法

You(构造大水题)

(这大水题也有2000分,真有意思 ……)

题意:给定一个整数n,要求构造出一个长度为n的字符串

字符串要求满足: 这个字符串中的所有子字符串的数量都为奇数。

这句话的意思是: 该字符串里面的所有字串的数量都得为奇数

样例:

3

abc

字串为:a, b, c, ab, ac, abc 均只出现了1次(奇数)

就这个意思👆

题解:只要构造出一种满足题意即可:

我的构造方法:

如果n = 9,那么就是 aaaabcaaa

如果n = 8,那么就是 aaaabaaa

即:分n为奇偶讨论 在这里插入图片描述 特判:n =1, n = 2, n = 3

Code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main() {
	int _;
	cin >> _;
	while (_--) {
	    int n;
	    cin >> n;
	    if (n == 1) { cout << 'a' << endl; continue; }
	    if (n == 2) { cout << "ab" << endl; continue; }
	    if (n == 3) { cout << "abc" << endl; continue; }
	    string s = "";
	    if (n & 1) {
	        for (int i = 1; i <= n / 2; i++) s += 'a';
	        s += "bc";
	        int len = n - (n / 2) - 2;
	        for (int i = 1; i <= len; i++) s += 'a';
 	    } else {
 	        for (int i = 1; i <= n / 2; i++) s += 'a';
 	        s += 'b';
 	        int len = n / 2 - 1;
 	        for (int i = 1; i <= len; i++) s += 'a';
 	    }
        cout << s << endl;
	}
	return 0;
}

总结:MEX和构造的题,更多是考思维能力,后面我会总结一下有关构造的题目,对于构造就是“见多识广”,思维自然开阔了。位运算真是个折磨人的玩意,对这方面还不太熟悉,关于这些脑筋急转弯的东西,有时候真的做不来,有时候灵机一动就想到了,道阻且长...,继续加油吧~