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

77 阅读1分钟

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

A. Meximization(思维)

题意:要使得Mex最大。

题解:将序列排序,将重复元素放到序列后面即可(没看题,看样例猜的,没想到对了)

const int N = 110;
int a[N];
int main() {
	int t, cin >> t;
	while (t--) {
		int n, cin >> n;
		vector<int> ans;
		for (int i = 1; i <= n; i++) cin >> a[i];
		sort(a + 1, a + n + 1);
		for (int i = 1; i <= n; i++) {
			if (a[i] == a[i + 1]) ans.push_back(a[i]);
			else cout << a[i] << " ";
		}
		for (int i = ans.size() - 1; i >= 0; i--) cout << ans[i] << " " << endl;
		cout << endl;
	}
	return 0;
}

B. M-arrays(思维)

题意: 给定一个序列a,a序列长度为n,还有一个m

要求找出序列a的子序列,要求满足 相邻的两个数之和能被m整除。

如果这个子序列只有一个数的话,就不需要满足被m整除这个条件。

题解:

对序列a中的数进行分组。

分几种情况:

假设m==7:

  1. 那么%3和%4的数之中,较多的数放在两边,较小的数放在中间,假设%3的数比较多,那么就是:3、4、3

  2. %7==0的,放一组

  3. 如果m是偶数的话,%4的,要和%2的在一组

const int N = 100010;
int a[N];
int main() {
	int t, cin >> t;
	while (t--) {
		int n, k, cin >> n >> k;
		for (int i = 1; i <= n; i++) {
			int x, cin >> x;
			a[x % m];  //分组 
		}
		
		if (a[0]) ans++; //%m=0的为1组 
		if (m % 2 == 0 && a[m / 2]) ans++; 
		if (m & 1) {
			for (int i = 1; i <= m / 2; i++) {
				int s = abs(a[m - i] - a[i]);
				if (s <= 1) if (a[i] > 0 || a[m - i] > 0) ans++;
				else ans += s;
			}
		} else {
			for (int i = 1; i <= m / 2 - 1; i++) {
				int s = abs(a[m - i] - a[i]);
				if (s <= 1) if (a[i] > 0 || a[m - i] > 0) ans++;
				else ans += s;
			}
		}
		cout << ans << endl;
	}
	return 0;
}

C1.k-LCM (easy version)(构造)

题意: 给定一个数字n,要求构造出一个序列满足

  1. a1+a2+a3=na_1+a_2+a_3=n

  2. LCM(a1,a2,a3)n2LCM(a_1,a_2,a_3)≤\frac{n}{2}

题解:

分类讨论:

  1. 当n为奇数的时候,将n分成,1、n/2、n/2

  2. 当n%2==2的时候,将n分成,2、(n-1)/2、(n-1)/2

  3. 当n%4==0的时候,将n分成,n/2、n/4、n/4

signed main() {
	int t, cin >> t;
	while (t--) {
		int n, k, cin >> n >> k;
		if (n & 1) cout << 1 << " " << n / 2 << " " << n / 2 << endl;
		else if (n % 4 == 2) {
			n -= 2;
			cout << 2 << " " << n / 2 << " " << n / 2 << endl; 
		} else cout << n / 2 << " " << n / 4 << " " << n / 4 << endl;
	}
	return 0;
}

C2.LCM(hard-version)(构造)

题意: 给定一个数字n,要求构造出一个序列满足:

  1. a1+a2+...+ak=na_1+a_2+...+a_k=n

  2. LCM(a1,a2,...,ak)n2LCM(a_1,a_2,...,a_k)≤\frac{n}{2}

其中 3kn3≤k≤n

这道题的解题思路与C1一模一样

首先将数字控制剩下3个,其余的全部输出1

对应操作就是,先算出需要k-3个1

然后剩下3个数,重复C1的操作就可以了

signed main() {
	int t, cin >> t;
	while (t--) {
		int n, k, cin >> n >> k;
		int a = k - 3;
		for (int i = 1; i <= k - 3; i++) cout << 1 << " ";
		n -= k - 3;
		if (n & 1) cout << 1 << " " << n / 2 << " " << n / 2 << endl;
		else if (n % 4 == 2) {
			n -= 2;
			cout << 2 << " " << n / 2 << " " << n / 2 << endl; 
		} else cout << n / 2 << " " << n / 4 << " " << n / 4 << endl;
	}
	return 0;
}