题目
第一题
键盘输入两个字符串,将这两个字符串进行拼接后输出。
输入描述
键盘输入两个字符串
输出描述
输出两个字符串拼接后的结果
例式1:
输入:
hello
nihao
输出:
hellonihao
解题思路
这个问题的解题思路非常简单,主要涉及两个步骤:
一是从键盘输入两个字符串。
二是将这两个字符串进行拼接。
以下是相应的解题思路的伪代码:
1. 从键盘输入字符串 str1
2. 从键盘输入字符串 str2
3. 将 str2 拼接到 str1 的后面,得到拼接后的字符串 result
4. 输出 result
同时也要确保你的输入符合题目的要求,并且程序的输出是正确的。如果在特定的在线评测系统中遇到问题,还需要确保你的程序满足该评测系统的输入输出规范。
代码如下:
#include <iostream>
#include <string>
int main() {
// 声明两个字符串变量
std::string str1, str2;
// 从键盘输入两个字符串
std::getline(std::cin, str1);
std::getline(std::cin, str2);
// 在两个字符串之间添加一个空格,并将它们进行拼接
std::string result = str1 + str2;
// 输出拼接后的结果
std::cout << result;
return 0;
}
第二题
擂台赛要开始了,现在有n名战士,其中第名战士的战斗力为a。现在准备从这些战士中挑两名战士进入擂台赛进行对战,由于观众们更喜欢看势均力敌的比赛,所以我们也要挑选两个战斗力尽可能相近的战士进行参赛。那么现在请问,战斗力最接近的两名战士,战斗力之差为多少?
输入:
第一行输入一行一个正整数n表示战士的数量
第二行输入 n 个正整数表示每名战上的战斗力。(1<=n<=10^5 ,1<=ai<=10^9)
输出描述
输出一行一个正整数表示答案
例1
输入
3
355
输出
0
说明
选择两名战斗力为 5 的战士,战斗力之差为 0
示例2
输入
5
1 10 4 9 6
输出
1
说明
选择战斗力为 10 和9 两名战上,战斗力的差值为 1
解题思路
这个问题的解题思路是先对战士的战斗力进行排序,然后遍历排序后的列表,找到相邻两个战士战斗力之差的最小值。以下是详细的解题步骤:
读取输入,获取战士的数量 n 和每名战士的战斗力列表。
对战斗力列表进行排序,这样相邻的战士战斗力就会挨在一起。
初始化一个变量 min_difference 为正无穷大,用来记录最小的战斗力差值。
遍历排序后的战士列表,计算相邻两个战士的战斗力差值,并更新 min_difference。
输出最终的 min_difference。
通过这种方式,你能够找到两名战士战斗力之差的最小值,从而满足观众更喜欢看到势均力敌的比赛的要求。
代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> powers(n);
for (int i = 0; i < n; ++i) {
cin >> powers[i];
}
sort(powers.begin(), powers.end());
int min_difference = INT_MAX;
for (int i = 1; i < n; ++i) {
int difference = powers[i] - powers[i - 1];
min_difference = min(min_difference, difference);
}
cout << min_difference << endl;
return 0;
}
第三题-红色和紫色-【第六届传智杯程序设计挑战赛解题分析详解复盘】(Java&Python&C++实现)
漫长的生命总是无聊的。这天,小红和紫准备玩一个染色游戏。
她们拿出了一个有 n* m 个格了的网格,每个格了只能被染成红色或紫色。每个人可以任意选择一个格了染成红色和紫色,两人轮流进行染色。
她们约定,不能有两个相邻的格子有相同的颜色。最后无法进行染色的人判输
小红先手进行染色。小红想知道,双方都采用最优策略的情况下,她能否取得胜利?
输入描述
两个正整数n和m,用空格隔开(1<= n, m <=10^9)
输出描述
如果小红获胜,则输出一个字符串"akai"
如果紫获胜,则输出一个字符串"yukari"
例1
输入
1 1
输出
akai
说明
小红直接把这个格子染成红色,即可获胜
示例2
输入
1 2
输出
yukari
说明
小红染色后,紫只需要在相邻的格子染上不同的颜色即可获胜
解题思路
首先,让我们分析一下这个游戏。两个玩家轮流在网格上染色,不能让相邻的格子具有相同的颜色,最后无法进行染色的一方判输。
关键观察点:
如果网格的行数和列数都是偶数,那么紫色方可以始终保持与红色相邻的颜色。这是因为如果红色方在某一行或某一列染色,紫色方总是可以选择相邻的行或列进行染色,使得相邻格子颜色不同,从而保持胜利。
如果网格的行数和列数有一个是奇数,那么红色方可以通过染色使得最后一行或最后一列只有一个格子。这是因为无论紫色方如何染色,红色方都可以选择染色使得最后一行或最后一列只有一个格子,从而获得胜利。
基于上述观察,我们可以得出判断胜负的规律,即:
如果网格的行数和列数都是偶数,紫色方获胜。
如果网格的行数和列数有一个是奇数,红色方获胜。
根据这个规律,可以编写上述修正后的代码。这个代码适用于判断胜负的情况,并考虑了双方采用最优策略的情况。
代码:
#include <iostream>
std::string game_winner(int n, int m) {
if ((n * m) % 2 == 0) {
return "yukari";
} else {
return "akai";
}
}
int main() {
int n, m;
std::cin >> n >> m;
// 输出结果
std::cout << game_winner(n, m) << std::endl;
return 0;
}
第四题-abb 【第六届传智杯程序设计挑战赛解题分析详解复盘】(Java&Python&C++实现)
leafee 最近爱上了 abb 型语句,比如“叠词词”、“恶心心”leafee 拿到了一个只含有小写字母的字符串,她想知道有多少个"abb"型的子序列?
定义: abb 型字符串满足以下条件:
1.字符串长度为 3
2.字符串后两位相同
3.字符串前两位不同
输入描述
第一行一个正整数n 第二行一个长度为 n的字符串 (只包含小写字母)
1<n<10^5
输出描述
"abb"型的子序列个数
例1
输入
6 abcbcc
输出
8
说明
共有1个abb,3个acc,4个bcc
示例2
输入
4
abbb
输出 3
解题思路
这道题的解题思路主要涉及到计算以字符串中每个字符为开头的 “abb” 型子序列的个数。具体来说,我们需要对字符串进行遍历,对于每个字符,统计该字符之后的两个字符中,有多少个与它们不同的字符。根据这个统计信息,我们可以计算以当前字符为开头的 “abb” 型子序列的个数。
以下是解题思路的详细步骤:
使用一个数组 ch 统计字符串中每个字符的出现次数。
初始化一个累加变量 total_sum 为 0,用于存储最终的结果。
遍历字符串,对于每个字符,执行以下步骤:
a. 将当前字符出现次数减一,表示不再考虑当前字符。
b. 对于剩余的字符,统计与当前字符不同的字符的个数,然后根据组合公式计算以当前字符为开头的 “abb” 型子序列的个数,将结果累加到 total_sum 中。
输出最终结果 total_sum。
这个思路的关键在于理解 “abb” 型子序列的定义,以及通过对每个字符的处理来计算满足条件的子序列个数。希望这样的解释能够帮助你更好地理解这道题目。
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
if (n < 3) {
cout << 0 << endl;
return 0;
}
string s;
cin >> s;
long long total_sum = 0;
vector<long long> dp(n, 0);
vector<int> ch(26, 0);
for (char c : s) {
ch[c - 'a']++;
}
for (int i = 0; i < n - 2; i++) {
ch[s[i] - 'a']--;
for (int j = 0; j < 26; j++) {
if (s[i] - 'a' != j) {
dp[i] += ch[j] * (ch[j] - 1) / 2;
}
}
}
for (int i = 0; i < n - 2; i++) {
total_sum += dp[i];
}
cout << total_sum << endl;
return 0;
}
第五题-kotori和素因子【第六届传智杯程序设计挑战赛解题分析详解复盘】(Java&Python&C++实现)
kotori拿到了一些正整数。她决定从每个正整数取出一个素因子。但是,kotori有强迫症,她不允许两不同的正整数取出相同的素因子。她想知道,最终所有取出的数的和的最小值是多少?
注:
若a%k==0,则称k是a的因子。
若一个数有且仅有两个因子,则称其是素数。显然1只有一个因子,不是素数。
输入描述
第一行一个正整数n,代表kotori拿到正整数的个数 第二行共有n个数ai,表示每个正整数的值 保证不存在两个相等的正整数。
1<=n<=10 2<=ai<=1000
输出描述
1个正整数,代表取出的素因子之和的最小值。若不存在合法的取法,则输出-1。
例1
输入
4 12 15 28 22
输出
17
说明
分别取3,5,7,2,可保证取出的数之和最小 例2 输入 5 4 5 6 7 8 输出 -1 备注 1<=n<=10 2<=ai<=1000
解题思路
这道题的解题思路基于以下几个关键点:
找到每个数的素因子: 对于每个给定的正整数,需要找到它的素因子。在代码中,通过遍历从 2 到该数本身的所有数,找出其中是素数的因子。
素数判断: 在代码中,使用了一个 isPrime 函数来判断一个数是否为素数。这个函数会检查一个数是否大于等于2,并且是否能被2到根号n之间的任何整数整除。如果能被整除,那么它不是素数。
深度优先搜索(DFS): 通过深度优先搜索来尝试不同的素因子组合,找到和的最小值。在DFS的过程中,需要注意每个素因子只能被选择一次,因此需要使用一个数组 vis 来标记素因子是否已经被选择。
初始化素数数组: 在代码中,使用 init 函数初始化了一个素数数组,用于在找素因子时进行快速判断。
结果输出: 最后,输出所有素因子和的最小值。如果不存在合法的取法,则输出-1。
这个问题的本质是一个组合优化问题,通过DFS搜索所有可能的组合,找到使得素因子和最小的情况。这种类型的问题通常可以使用回溯法,深度优先搜索等方法来解决。
#include <bits/stdc++.h>
using namespace std;
int n;
int vis[1005];
vector<int> v[105];
int ans=999999;
const int MAX = 1000005;
bool prime[MAX];
void init() {
memset(prime,true,sizeof prime);
for(int i=2; i*i<MAX; i++) {
if(prime[i]) {//是素数
for(int j=i*2; j<MAX; j+=i)//从2倍开始,n倍
prime[j]=false;//各个倍数
}
}
}
void dfs(int d,int sum){
if(d==n){
ans=min(ans,sum);
return ;
}
for(int i=0;i<v[d].size();i++){
if(!vis[v[d][i]]){
vis[v[d][i]]=1;
dfs(d+1,sum+v[d][i]);
vis[v[d][i]]=0;
}
}
}
int main(){
init();
scanf("%d",&n);
for(int i=0;i<n;i++){
int temp;
scanf("%d",&temp);
for(int j=2;j<=temp;j++){
if(temp%j==0&&prime[j]){
v[i].push_back(j);
//cout<<j<<" ";
}
}
//cout<<endl;
}
dfs(0,0);
if(ans==999999)
printf("-1\n");
else
printf("%d\n",ans);
return 0;
}
第六题-红和蓝【第六届传智杯程序设计挑战赛解题分析详解复盘】(Java&Python&C++实现)
你拿到了一棵树,请你给每个顶点染成红色或蓝色。
要求: 每个红点周围有且仅有一个红点,每个蓝点周围有且仅有一个蓝点。
周围”的定义:某点周围的点指通过邻边直接连接的点所谓树,即没有自环、重边和回路的无向连通图。
输入描述
第一行一个正整数n,代表树的顶点个数.(1<n<100000)
接下来的n-1行,每行两个正整数u和v,代表点u 和点v有一条边连接。 (1<=u,v<=n)保证输入的一定是一棵合法的树。
输出描述
如果可以达成染色的要求,请输出一个长度为 n 的字符串,第i个字符代表第i个顶点的染色情况,B 代表蓝色,R代表红色(若有多种合法染色的方法,输出任意1种即可)
否则直接输出-1
例示1:
输入:
4
1 2
2 3
3 4
输出:
RRBB
说明:
1为红点,它连接的边有只有一个红点: 2
2为红点,它连接的边有只有一个红点: 1
3为蓝点,它连接的边有只有一个蓝点: 4
4为蓝点,它连接的边有只有一个蓝点: 3
示例2:
输入
4
1 2
1 3
1 4
输出
-1
说明:
可以证明,无论怎么染色,都无法满足题目的要求。
解题思路
这个问题是一个树的染色问题,要求每个顶点染成红色或蓝色,并且满足以下条件:
每个红点周围有且仅有一个红点。
每个蓝点周围有且仅有一个蓝点。
解题思路主要分为两步:
第一次深度优先搜索(DFS):遍历树,标记每个节点的标记信息(dp数组),并检查是否有孤立的节点。孤立的节点意味着无法满足染色条件。
第二次DFS:根据第一次DFS的标记信息,确定每个节点的颜色。
具体的步骤如下:
使用邻接表表示树的结构,构建一个图。
第一次DFS:从根节点开始遍历整个树,标记每个节点的标记信息(dp数组)。如果发现孤立的节点或者某个节点被多次标记,说明无法满足染色条件,输出-1。
第二次DFS:根据第一次DFS得到的标记信息,确定每个节点的颜色,使得满足染色条件。
这类问题的关键在于通过深度优先搜索(DFS)遍历整个树,同时根据问题要求进行合理的标记和操作。
#include <stdio.h>
#include <string.h>
int mark = 0; //标记同色的父子节点
int head[100010]; // 存储树的索引节点
struct ty {
int value; // 边的值
int next; // 相邻边的索引
} edge[200010];
int dp[100010] = {0}; // 第一次DFS时,每个点的标记信息
int color[100010] = {0}; // 第二次DFS时,记录每个节点的颜色信息
/* 添加新的边到树型结构中 */
void addedge(int x, int y, int pos) {
edge[pos].value = y;
edge[pos].next = head[x];
head[x] = pos;
}
int dfs1(int x, int father) {
int son = 0;
for (int i = head[x]; i != -1; i = edge[i].next) {
if (edge[i].value != father) { // 避免回环
++son;
if (dfs1(edge[i].value, x)) return 1;
}
}
// son==0表示叶子节点 ; dp[x]==0 表示 x 这个点未被标记
if (son == 0 || dp[x] == 0) {
if (dp[father] != 0) return 1; // 一个节点被多次标记,无解
dp[x] = dp[father] = ++mark;
}
return 0;
}
void dfs2(int x, int father) {
for (int i = head[x]; i != -1; i = edge[i].next) {
if (edge[i].value != father) { // 避免回环
if (dp[edge[i].value] == dp[x])
color[edge[i].value] = color[x]; // 两个节点标记相同,则颜色相同
else
color[edge[i].value] = !color[x]; // 两个节点标记不同,则颜色不同
dfs2(edge[i].value, x);
}
}
}
int main() {
int x, y, n, pos = 1;
scanf("%d", &n);
memset(head, -1, sizeof(head));
memset(edge, -1, sizeof(edge));
for (int i = 1; i < n; ++i) {
scanf("%d%d", &x, &y);
addedge(x, y, pos);
++pos;
addedge(y, x, pos);
++pos;
}
// 1==dfs1(1,0) 表示无解
// dp[0] 其实是整个树的第一个节点的根节点,上面的code中,我们的树是从pos==1开始的
// 也就是第一个节点的标记信息在dp[1]中,这里使用dp[0]就是为了观察第一个节点(dp[1])有没有被孤立
// 如果孤立了则dp[0]一定被标记了,反之dp[0]一定为0
if (dfs1(1, 0) || dp[0]) {
printf("-1");
return 0;
}
color[1] = 1; // 这里也可以是0,题目也说了可能多解
dfs2(1, 0);
for (int i = 1; i <= n; ++i) {
printf("%c", color[i] ? 'R' : 'B');
}
return 0;
}