习题训练五 题解

A - Sum of Odd Integers

 1.题意

  给定正整数 n 和 k,问 n 是否能被 k 个不同的奇数相加所得。

 2.题解

  奇数能被奇数个奇数构成,偶数能被偶数个奇数构成,所以 n 和 k 奇偶性必须相同,用等差数列得k 个不同的奇数所能构成的最小 n 是 k * k (1 + 3 + 5 + ··· +(2 * k)- 1 ),显然对于更大的 n 可以通过把小奇数不断+2所得到,所以只要n 和 k 奇偶性相同且 n >= k * k 即可。

 3.代码

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int maxn = 2e6 + 5;
int t; 
int main() {
	ios::sync_with_stdio(false);
	cin >> t;
	while(t--) {
		ll n, k;
		cin >> n >> k; 
	
		int flag1 = n % 2;
		int flag2 = k % 2;
		if(flag1 == flag2 && n >= k * k) {
			cout << "YES" << endl;
		} else {
			cout << "NO" << endl;
		}		
	}

	return 0;
}

B - Princesses and Princes

 1.题意

  有 n 个公主和 n 个王子,每个公主都有一份对王子的喜爱名单(喜欢哪几个王子),公主按下标顺序在自己的喜爱名单中依次选取王子,前提是这个王子还没被别的公主选中,下标小的王子优先被选中,如果最后每个公主都选到了属于自己的王子,则输出“OPTIMAL”,否则让你给某个选取失败的公主寻找一位单身王子(显然,该王子没在这个公主的喜爱名单里),输出“IMPROVE”并输出这个公主和王子的下标,如果有多个解决方案,输出任意一个即可。

 2.题解

  模拟即可,用一个桶维护王子的状态,用 ans 记录选取失败的公主。

 3.代码

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int maxn = 2e5 + 5;
int t; 
int main() {
	ios::sync_with_stdio(false);
	cin >> t;
	while(t--) {
		int n;
		cin >> n; 
		int a[n + 5] = {0};
		int cnt;
		int ans = 0;
		
		for(int i = 1; i <= n; i++) {		
			cin >> cnt;
			int flag = 0;
			for(int j = 1; j <= cnt; j++) {
				int v;
				cin >> v;
				if(a[v] == 0 && flag == 0) {
					a[v] = 1;
					flag = 1;
				}
			}
			if(flag == 0) {
				ans = i;
			}
		}
		
		if(ans == 0) {
			cout << "OPTIMAL" << endl;
		} else {
			cout << "IMPROVE" << endl;	
			for(int j = 1; j <= n; j++) {
				if(a[j] == 0) {
					cout << ans << ' ' << j << endl;
					break;
				}
			}		
		}		
	}

	return 0;
}

  

C - EhAb AnD gCd

 1.题意

  给定一个正整数 x,让你找到两个正整数 a,b,使得 a,b 的最大公约数和最小公倍数之和为 x,如果有多组答案,输出任意一组即可。

 2.题解

  任意一个数与1的最大公约数是1,最小公倍数是这个数,所以直接输出1和 x - 1即可。

 3.代码

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int maxn = 2e5 + 5;
int t; 
int main() {
	ios::sync_with_stdio(false);
	cin >> t;
	while(t--) {
		int x;
		cin >> x; 
		
		cout << 1 << ' ' << x - 1 << endl;
	}

	return 0;
}

  

D - CopyCopyCopyCopyCopy

 1.题意

  给定一个整数数组 a,我们可以对 a 复制任意多次放进数组 b,然后可以对数组 b 进行任意元素的删除,得到一个严格递增序列,输出序列的长度。

 2.题解

  因为可以复制任意多次,所以考虑最坏情况,第一次复制把除最小之外的数都删除,第二次把除倒数第二小之外的数都删除,以此类推,所以只要把数组 a 中重复的元素去掉即可,可以用 set 自动去重。

 3.代码

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int maxn = 2e5 + 5;
int t; 
int main() {
	ios::sync_with_stdio(false);
	cin >> t;
	while(t--) {
		int n;
		cin >> n; 
		set<int> st;
		int v;
		for(int i = 1; i <= n; i++) {
			cin >> v;
			st.insert(v);
		}
		
		cout << st.size() << endl;
	}

	return 0;
}

  

F - Yet Another Tetris Problem

 1.题意

  给定 n 列俄罗斯方块,每列的高度是 ai,只能向上添加高度为2,宽度为1的方块,问最后是否能把所有俄罗斯方块全部消除。

 2.题解

  如果其中任意两列的高度差为奇数,则无法用高度为2的方块使它们高度相等,所以遍历每列高度,判断奇偶性,如果有一列与第一列高度奇偶性不同,说明它们的高度差是奇数,无法完成消除。另外,如果只有一列,直接可以消除。

 3.代码

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int maxn = 2e5 + 5;
int t; 
int main() {
	ios::sync_with_stdio(false);
	cin >> t;
	while(t--) {
		int n;
		cin >> n; 
		int a[n + 5] = {0}; 
		
		for(int i = 1; i <= n; i++) {
			cin >> a[i];
		}
		
		if(n == 1) {
			cout << "YES" <<endl;
			continue;
		}
		
		int x = a[1] % 2;
		int flag = 1;
		for(int i = 2; i <= n; i++) {
			if(a[i] % 2 != x) {
				flag = 0;
				break;
			}
		}
		if(flag) {
			cout << "YES" <<endl;
		} else {
			cout << "NO" <<endl;
		}
		
	}

	return 0;
}

  

G - Yet Another Palindrome Problem

 1.题意

  给定一个由正整数组成的数组,要求找到一个长度至少为3的回文子序列(子序列的元素在原序列中不必连续)。

 2.题解

  既然长度至少为3,那就判断长度为3的子序列,用两层循环判断 i + 1之后是否有与 ai 相同的元素。 

 3.代码

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int maxn = 2e5 + 5;
int t; 
int main() {
	ios::sync_with_stdio(false);
	cin >> t;
	while(t--) {
		int n;
		cin >> n; 
		int a[n + 5] = {0}; 
		
		for(int i = 1; i <= n; i++) {
			cin >> a[i];
		}
		
		int flag = 0;
		for(int i = 1; i <= n - 2; i++) {
			for(int j = i + 2; j <= n; j++) {
				if(a[i] == a[j] ) {
					flag = 1;
					break;
				}
			}	
			if(flag) {
				break;
			}		
		}
	
		if(flag) {
			cout << "YES" <<endl;
		} else {
			cout << "NO" <<endl;
		}
		
	}

	return 0;
}

  

H - Frog Jumps

 1.题意

  有一个青蛙尝试从坐标0跳过一个数组,数组从1到 n,数组上的元素是L或R,意味着青蛙在这个单元格上只能向左或向右跳,在坐标0式只能向右跳,求出青蛙能完成任务的最长跳跃长度的最小值。

 2.题解

  只要青蛙能跳过连续的L,就能最终到达终点,所以找到连续的最长L的长度再加一即可,可以用前缀和记录L的连续长度,用变量 ans 维护最大值。

 3.代码

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int maxn = 2e5 + 5;
int t; 
int main() {
	ios::sync_with_stdio(false);
	cin >> t;
	while(t--) {
		string s;
		cin >> s; 
		
		int n = s.size();
		int a[n + 5] = {0};
		if(s[0] == 'L') {
			a[0] = 1;
		}
		
		int ans = a[0];
		for(int i = 1; i < n; i++) {
			if(s[i] == 'L') {
				a[i] += a[i - 1];
				a[i]++;
			} else {
				a[i] = 0;
			}	
			ans = max(ans, a[i]);	
		}
	
		cout << ans + 1 << endl;
	}

	return 0;
}

  

原文地址:https://www.cnblogs.com/lvguapi/p/13071275.html