杭电oj(2013-2028)题解
目录
编辑
2013
题目
思路
代码
2014
题目
思路
代码
2015
题目
思路
整体思路
情况一:n 能被 m 整除
情况二:n 不能被 m 整除
重置向量
代码
2016
题目
思路
核心思路
排序和查找最小值
交换最小值和第一个元素
代码
2017
题目
思路
核心思路
代码
2018
题目
思路
代码
2019
题目
思路
代码
2020
题目
思路
代码
2021
题目
思路
整体思路
代码
2022
题目
思路
代码
2023
题目
思路
成绩数据读取
计算学生平均成绩
计算课程平均成绩
统计满足条件的学生数量
代码
2024
题目
思路
循环处理每个字符串
检查字符串的第一个字符
检查字符串中的每个字符
代码
2025
题目
思路
字符存储与排序
找出最大字符
处理字符串并添加标记
输出结果并重置变量
代码
2026
题目
思路
代码
2027
题目
思路
代码
2028
题目
思路
代码
2013
题目
思路
数学公式2*(x+1),逐步迭代ans和num即可
代码
#include<iostream>
#include<algorithm>
using namespace std;
int n,ans,num;
int main(){while(cin>>n){num=1;ans=1;for(int i=1;i<n;i++){ans=2*(num+1);num=ans;}cout<<ans<<endl;}return 0;
}
2014
题目
思路
利用vector动态数组存储元素,进行排序,计算下标1~size-1的平均数,每次计算后别忘了清空数组,sum也要重置。
注释的部分是为了检查数组中的元素。
代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int n,m;
double sum,pjf,num;
vector<int> sc;
int main(){while(cin>>m){sum=0;for(int j=0;j<m;j++){cin>>num;sc.push_back(num);}sort(sc.begin(),sc.end());
// for(int ii=0;ii<sc.size();ii++){
// cout<<sc[ii]<<" ";
// }for(int ii=1;ii<sc.size()-1;ii++){sum+=sc[ii];}pjf=sum/(sc.size()-2);printf("%.2lf\n",pjf); for(int j=0;j<m;j++){sc.erase(sc.begin());}}return 0;
}
2015
题目
思路
整体思路
程序会持续从标准输入读取两个整数
n
和m
,其中n
表示要生成的偶数序列的元素数量,m
表示分组的每组元素个数。接着,程序会生成一个包含n
个偶数的序列,然后按照每组m
个元素对该序列进行分组。最后,计算并输出每组的平均值。情况一:
n
能被m
整除
cnt
代表分组的数量,其值为n/m
。- 利用外层
for
循环遍历每一组,内层for
循环计算当前组内所有元素的和sum
。- 每组元素的平均值
pjs
为sum/m
,并将其输出。lxb
和rxb
分别表示当前组的起始和结束索引。情况二:
n
不能被m
整除
- 首先处理前面能完整分组的部分,这部分的处理方式与情况一相同。
- 接着处理剩余的元素,这些元素构成最后一组。
- 计算最后一组元素的和
sum
,其平均值pjs
为sum/(n - zxb)
,并将其输出。重置向量
在处理完一组输入后,将向量
a
清空,为下一组输入做准备。该程序的核心思路是生成一个偶数序列,按指定长度分组,计算每组的平均值并输出。同时,程序会处理
n
不能被m
整除的情况,确保所有元素都能得到处理。
代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int n,m;
vector<int> a;
int main(){while(cin>>n>>m){for(int i=1;i<=n;i++){a.push_back(i*2);}int cnt=0,sum=0,pjs=0;if(n==(n/m)*m){cnt=n/m;int lxb=0;for(int j=1;j<=cnt;j++){sum=0,pjs=0;int rxb=m*j;for(int l=lxb;l<rxb;l++){sum+=a[l];}pjs=sum/m;cout<<pjs<<" ";lxb=rxb;}}else{cnt=n/m;int lxb=0;for(int j=1;j<=cnt;j++){sum=0,pjs=0;int rxb=m*j;for(int l=lxb;l<rxb;l++){sum+=a[l];}pjs=sum/m;cout<<pjs<<" ";lxb=rxb;}sum=0;int zxb=(n/m)*m;for(int e=zxb;e<n;e++){sum+=a[e];}pjs=sum/(n-zxb);cout<<pjs<<" ";}//重置数组;for(int l=0;l<n;l++){a.erase(a.begin());}cout<<endl;}return 0;
}
2016
题目
思路
核心思路
不断从标准输入读取整数序列,对每个序列进行处理,将序列中的最小值与序列的第一个元素交换位置,然后输出处理后的序列,直到输入的序列长度为 0 时停止。
排序和查找最小值
- 使用
sort
函数对数组a
进行升序排序。排序后,数组a
的第一个元素a[0]
即为原始序列中的最小值。交换最小值和第一个元素
- 使用
for
循环遍历数组b
,找到值等于a[0]
(即最小值)的元素。- 当找到最小值所在的位置
j
时,使用临时变量temp
交换b[j]
和b[0]
的值,将最小值放到数组b
的第一个位置。这段代码的核心就是不断读取整数序列,找出序列中的最小值并将其与序列的第一个元素交换位置,最后输出处理后的序列,直到输入的序列长度为 0 为止。
代码
#include<iostream>
#include<algorithm>
#include<vector>
int n;
int a[10000],b[10000];
using namespace std;
int main(){while(cin>>n){if(n==0) break;for(int i=0;i<n;i++){cin>>a[i];b[i]=a[i];}sort(a,a+n);for(int j=0;j<n;j++){if(b[j]==a[0]){int temp=b[j];b[j]=b[0];b[0]=temp;}}for(int j=0;j<n;j++){cout<<b[j]<<" ";}cout<<endl;}return 0;
}
2017
题目
思路
核心思路
这段代码的核心流程是先读取要处理的字符串数量,接着循环读取每个字符串,统计其中数字字符的数量并输出,直到处理完所有字符串。
cin>>n;
:从标准输入读取一个整数n
,该整数表示接下来要读取的字符串的数量。cin.ignore();
:忽略掉cin>>n;
后输入缓冲区中的换行符,避免影响后续getline
函数的读取。因为cin
在读取整数后,换行符会留在输入缓冲区,而getline
会读取这个换行符,导致读取到空字符串。
代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
int n,cnt;
string s;
int main(){cin>>n;cin.ignore(); for(int i=0;i<n;i++){getline(cin,s);cnt=0;for(int j=0;j<s.size();j++){if(s[j]>='0' && s[j]<='9') cnt++;}cout<<cnt<<endl;}return 0;
}
2018
题目
思路
该题的核心就是根据输入的
n
计算特定数列的第n
项,该数列的前 4 项分别为 1、2、3、4,从第 5 项开始,每一项等于前一项与前三项之和,最后输出计算得到的第n
项的值。因为题目中说明了第四年才可以生小母牛
for(int i = 1; i <= n; i++)
:使用for
循环从第 1 项开始,依次计算数列的每一项,直到第n
项。if(i <= 4) a[i] = i;
:当i
小于等于 4 时,数列的第i
项就等于i
,即a[1]=1
,a[2]=2
,a[3]=3
,a[4]=4
。else { a[i] = a[i - 1] + a[i - 3]; }
:当i
大于 4 时,数列的第i
项等于第i - 1
项与第i - 3
项之和。
代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int n;
int a[100000];
int main(){while(cin>>n){if(n==0) break;for(int i=1;i<=n;i++){if(i<=4) a[i]=i;else{a[i]=a[i-1]+a[i-3];}}cout<<a[n]<<endl;}return 0;
}
2019
题目
思路
这段代码的核心是依据整数
m
和数组a
中元素的大小关系,把m
插入到合适的位置,保证插入后的数组b
依旧有序。通过flag
变量来标记m
是否已经插入,避免重复插入。
- 初始化变量
j
用于记录数组b
的当前索引,flag
用于标记整数m
是否已经插入到数组b
中。- 若
m
小于等于数组a
的第一个元素,就把m
放到数组b
的第一个位置,将flag
置为 1 表示m
已插入,同时j
加 1。- 若
m
大于等于数组a
的最后一个元素,就把m
放到数组b
的最后一个位置(索引为n
),并将flag
置为 1。- 遍历数组
a
,若m
还未插入(flag
为 0)且m
小于等于当前元素a[i]
,就把m
插入到数组b
中,将flag
置为 1。- 把数组
a
的当前元素a[i]
复制到数组b
中。- 若遍历完数组
a
后m
仍未插入(flag
为 0),就把m
放到数组b
的当前位置。
代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int n,m;
int a[10000],b[10000+1];
int main(){while(cin>>n>>m){if(n==0 && m==0) break;for(int i=0;i<n;i++){cin>>a[i];}int j=0;int flag=0;if(a[0]>=m) {//最前面 b[0]=m;flag=1;j++;}if(a[n-1]<=m){//最后面 b[n]=m;flag=1;}for(int i=0;i<n;i++){//中间 if(!flag && m <= a[i]){b[j++]=m; flag=1;}b[j++]=a[i];}if(!flag) b[j]=m;for(int i=0;i<n+1;i++){cout<<b[i]<<" ";}cout<<endl;}return 0;
}
2020
题目
思路
该题的核心就是不断读取整数序列,使用冒泡排序算法按照元素绝对值从大到小对序列进行排序,最后输出排序后的序列,直到输入的序列长度为 0 为止。
- 这题使用冒泡排序算法对数组
a
进行排序,排序的依据是元素的绝对值大小。- 外层
for
循环控制排序的轮数,总共需要进行n - 1
轮。- 内层
for
循环用于比较每一轮中相邻元素的绝对值大小。if(abs(a[i]) < abs(a[j]))
:如果a[i]
的绝对值小于a[j]
的绝对值,则交换这两个元素的位置,使得绝对值大的元素逐渐 “冒泡” 到前面。
代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<math.h>
using namespace std;
int n,num;
int a[200];
int main(){while(cin>>n){if(n==0) break;for(int i=0;i<n;i++){cin>>a[i];}//冒泡排序for(int i=0;i<n-1;i++){for(int j=i;j<n;j++){if(abs(a[i])<abs(a[j])){int temp=a[j];a[j]=a[i];a[i]=temp;}}}for(int i=0;i<n;i++){cout<<a[i]<<" ";} cout<<endl;}return 0;
}
2021
题目
思路
整体思路
- 输入处理:程序会持续从标准输入读取工资数额的数量
n
,直到输入的n
为 0 时停止。对于每个非零的n
,程序会接着读取n
个具体的工资数额。- 单金额纸币数量计算:对于每个读取到的工资数额,使用贪心算法计算出用给定面额纸币组成该金额所需的最少纸币数量。
- 结果累加与输出:将每个工资数额对应的最少纸币数量累加起来,最后输出这个累加的总数。
代码
#include <iostream>
#include <vector>
using namespace std;
int money_cnt(int num) {int cnt = 0;vector<int> denominations = {100, 50, 10, 5, 2, 1};for (int denomination : denominations) {cnt += num / denomination;num %= denomination;}return cnt;
}int main() {int n, gz, ans;while (cin >> n) {ans = 0;if (n == 0) break;for (int i = 0; i < n; i++) {cin >> gz;ans += money_cnt(gz);}cout << ans << endl;}return 0;
}
2022
题目
思路
该题的核心是通过嵌套循环读取矩阵的元素,在读取过程中比较每个元素的绝对值,找出绝对值最大的元素,记录其位置,最后输出该元素的位置和值。通过
while
循环可以处理多组矩阵输入。
- 外层
for
循环for(int i = 1; i <= h; i++)
:遍历矩阵的每一行,行号从 1 到h
。- 内层
for
循环for(int j = 1; j <= l; j++)
:遍历当前行的每一列,列号从 1 到l
。cin>>a[i][j];
:从标准输入读取矩阵中第i
行第j
列的元素,并存储到二维数组a
中。if(abs(a[i][j])>abs(max))
:比较当前元素a[i][j]
的绝对值和max
的绝对值,如果当前元素的绝对值更大,就更新eh
和el
为当前元素的行号和列号,同时更新max
为当前元素的值。
代码
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int h,l;
int a[10000][10000];
int main(){while(cin>>h>>l){int eh=0,el=0;int max=0;for(int i=1;i<=h;i++){for(int j=1;j<=l;j++){cin>>a[i][j];if(abs(a[i][j])>abs(max)){eh=i;el=j;max=a[i][j];}}}cout<<eh<<" "<<el<<" "<<max<<endl;}return 0;
}
2023
题目
思路
该题通过嵌套循环实现了成绩数据的读取、学生平均成绩和课程平均成绩的计算,以及特定条件下学生数量的统计,并按照要求输出结果。
成绩数据读取
- 运用嵌套的
for
循环读取成绩数据。外层循环遍历每个学生,内层循环遍历每门课程。- 把读取到的成绩存储在二维数组
a
中,a[i][j]
表示第i
个学生的第j
门课程的成绩。计算学生平均成绩
- 外层
for
循环遍历每个学生。- 针对每个学生,先将
sum
初始化为 0,接着通过内层for
循环累加该学生所有课程的成绩。- 计算该学生的平均成绩,将其存储在数组
c
中,c[i]
即为第i
个学生的平均成绩。- 使用
printf("%.2lf ", c[i]);
以保留两位小数的格式输出该学生的平均成绩。- 所有学生的平均成绩输出完毕后,输出换行符。
计算课程平均成绩
- 外层
for
循环遍历每门课程。- 对于每门课程,先将
sum
初始化为 0,然后通过内层for
循环累加所有学生该课程的成绩。- 计算该课程的平均成绩,将其存储在数组
b
中,b[i]
即为第i
门课程的平均成绩。- 使用
printf("%.2lf ", b[i]);
以保留两位小数的格式输出该课程的平均成绩。- 所有课程的平均成绩输出完毕后,输出换行符。
统计满足条件的学生数量
- 外层
for
循环遍历每个学生。- 对于每个学生,将标志变量
flag
初始化为 1,表示假设该学生所有课程成绩均高于课程平均成绩。- 内层
for
循环遍历该学生的每门课程成绩,若发现某门课程成绩低于对应课程的平均成绩,就将flag
置为 0。- 若
flag
仍为 1,说明该学生所有课程成绩均高于课程平均成绩,将计数器cnt
加 1。- 最后输出满足条件的学生数量。
代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int n,m,cnt;
double sum;
double a[100][100];
double b[100];//课程平均成绩
double c[100];//学生平均成绩
int main(){while(cin>>n>>m){cnt=0;for(int i=0;i<n;i++){for(int j=0;j<m;j++){cin>>a[i][j]; }}for(int i=0;i<n;i++){sum=0;for(int j=0;j<m;j++){sum+=a[i][j];}c[i]=sum/m;printf("%.2lf ",c[i]);} cout<<endl;for(int i=0;i<m;i++){sum=0;for(int j=0;j<n;j++){sum+=a[j][i];}b[i]=sum/n;printf("%.2lf ",b[i]);}cout<<endl;for(int i=0;i<n;i++){int flag=1;for(int j=0;j<m;j++){if(a[i][j]<b[j]) flag=0; }if(flag) cnt++;}cout<<cnt<<endl;}return 0;
}
2024
题目
思路
这道题的核心是对输入的多个字符串进行合法性检查,要求字符串不能以空格或数字开头,且只能包含下划线、数字、大小写字母。根据检查结果输出
"yes"
或"no"
。循环处理每个字符串
for(int i = 0; i < n; i++)
:通过循环n
次,依次读取n
个字符串。getline(cin, s);
:从标准输入读取一行字符串,并将其存储到s
中。int flag = 1;
:初始化一个标志变量flag
为 1,表示假设当前字符串是合法的。检查字符串的第一个字符
- 检查字符串的第一个字符是否为空格或者是数字。如果是,则将
flag
置为 0,表示该字符串不合法。这是为了确保字符串不能以空格或数字开头。检查字符串中的每个字符
- 使用
for
循环遍历字符串中的每个字符。- 检查每个字符是否为下划线、数字、小写字母或大写字母。如果不是,则将
flag
置为 0,表示该字符串不合法,并使用break
语句跳出循环,因为只要有一个不合法字符,整个字符串就不合法。
代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
int n;
string s;
int main(){cin>>n;cin.ignore();for(int i=0;i<n;i++){getline(cin,s);int flag=1;if(s[0]==' ' || (s[0]<='9' && s[0]>='0')){flag=0;}for(int j=0;j<s.size();j++){if(!((s[j]=='_') || (s[j]>='0' && s[j]<='9') || (s[j]>='a' && s[j]<='z') || (s[j]>='A' && s[j]<='Z'))){flag=0;break;} }if(flag) cout<<"yes"<<endl;else cout<<"no"<<endl;}return 0;
}
2025
题目
思路
核心思路是从标准输入循环读取字符串,对每个字符串中的字符进行排序,找出其中最大的字符,然后将原字符串中的最大字符后面添加
(max)
标记,最后输出处理后的字符串。字符存储与排序
- 第一个
for
循环遍历输入的字符串s
,将字符串中的每个字符依次添加到向量a
中。sort(a.begin(), a.end());
:使用std::sort
函数对向量a
中的字符进行升序排序。排序后,向量a
中的最后一个字符即为最大字符。找出最大字符
- 由于向量
a
已经排序,所以向量a
中索引为s.size() - 1
的字符就是最大字符,将其存储到max_char
中。处理字符串并添加标记
- 第二个
for
循环遍历原字符串s
。- 如果当前字符不等于最大字符
max_char
,则直接将该字符添加到结果字符串ans
中。- 如果当前字符等于最大字符
max_char
,则将该字符和标记字符串add_s
依次添加到结果字符串ans
中。输出结果并重置变量
cout << ans << endl;
:输出处理后的字符串结果。ans = "";
:将结果字符串ans
重置为空字符串,以便处理下一个输入的字符串。- 第三个
for
循环通过a.erase(a.begin());
依次删除向量a
中的元素,将向量a
清空,为处理下一个字符串做准备。
代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
vector<char> a;
string ans;
string s;
string add_s="(max)";
int main(){while(cin>>s){for(int i=0;i<s.size();i++){a.push_back(s[i]);}sort(a.begin(),a.end());char max_char=a[s.size()-1];for(int i=0;i<a.size();i++){if(s[i]!=max_char) ans+=s[i];else ans=ans+s[i]+add_s;}cout<<ans<<endl;//重置 ans="";for(int i=0;i<s.size();i++){a.erase(a.begin());}}return 0;
}
2026
题目
思路
这道题的核心思路是通过循环读取多行字符串,然后遍历每行字符串中的每个字符,将每个单词的首字母转换为大写,最后输出转换后的字符串。需要注意的是,这段代码假设输入的字符串中每个单词之间只有一个空格,并且没有处理字符串为空或第一个字符不是字母的情况。
s[0]-=32;
:将字符串的第一个字符转换为大写。在 ASCII 码表中,小写字母的 ASCII 码值比对应的大写字母的 ASCII 码值大 32,因此减去 32 可以将小写字母转换为大写字母。- 使用
for
循环遍历字符串中的每个字符:
- 如果当前字符是空格
' '
,则将下一个字符转换为大写,即s[i+1]-=32;
。
代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>using namespace std;
int main(){string s;while(getline(cin,s)){s[0]-=32;for(int i=1;i<s.size();i++){if(s[i]==' '){s[i+1]-=32;}}cout<<s<<endl;}return 0;
}
2027
题目
思路
该题通过读取指定行数的字符串,逐个统计每行字符串中元音字母的出现次数,并输出统计结果,为后续的数据分析或者文本处理提供了基础的元音字母分布信息。不过代码仅统计小写元音字母,若要统计大写元音字母,需要添加相应的判断逻辑。
for
循环会执行n
次,每次处理一行输入的字符串。- 在每次循环开始时,将记录元音字母出现次数的变量
a
、e
、i
、o
、u
都重置为 0。getline(cin, s);
:从标准输入读取一行字符串,存于变量s
中。- 通过
for
循环遍历当前字符串s
中的每个字符。- 若字符是元音字母
a
、e
、i
、o
、u
中的一个,就将对应的计数变量加 1。
代码
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int n;
string s;
int a,e,i,o,u;
int main(){cin>>n;cin.ignore();for(int i1=0;i1<n;i1++){a=0,e=0,i=0,o=0,u=0;getline(cin,s);for(int j=0;j<s.size();j++){if(s[j]=='a') a++;else if(s[j]=='e') e++;else if(s[j]=='i') i++;else if(s[j]=='o') o++;else if(s[j]=='u') u++;}cout<<"a:"<<a<<endl;cout<<"e:"<<e<<endl;cout<<"i:"<<i<<endl;cout<<"o:"<<o<<endl;cout<<"u:"<<u<<endl;cout<<endl;}return 0;
}
2028
题目
思路
利用
gcd
和lcm
函数,逐步计算每组数据中所有整数的最小公倍数并输出结果。需要注意的是,数组arr
的大小是固定的,如果输入的整数个数超过 10000,可能会导致数组越界。
gcd
函数使用欧几里得算法(辗转相除法)计算两个整数a
和b
的最大公约数。lcm
函数根据公式lcm(a, b) = (a * b) / gcd(a, b)
计算两个整数a
和b
的最小公倍数,为避免溢出,先进行除法运算再进行乘法运算。while(cin>>n)
:通过循环不断从标准输入读取每组数据中整数的个数n
,直到输入结束。- 第一个
for
循环:将每组输入的n
个整数依次存储到数组arr
中。- 初始化操作:先将数组的前两个元素分别赋值给
a
和b
,然后调用lcm
函数计算这两个数的最小公倍数并存储在c
中。- 第二个
for
循环:从数组的第三个元素开始,依次将当前元素赋值给b
,将之前计算得到的部分最小公倍数c
赋值给a
,然后再次调用lcm
函数计算新的最小公倍数并更新c
的值。cout<<c<<endl;
:输出每组数据中所有整数的最小公倍数。
代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<math.h>
#include <numeric>
using namespace std;
// 计算最大公约数的函数
int gcd(int a, int b) {while (b != 0) {int temp = b;b = a % b;a = temp;}return a;
}// 计算最小公倍数的函数
int lcm(int a, int b) {return (a / gcd(a, b)) * b;
}
int n,a,b,c;
int arr[10000];
int main(){while(cin>>n){for(int i=0;i<n;i++){cin>>arr[i];}a=arr[0];b=arr[1];c=lcm(a,b);for(int i=2;i<n;i++){ b=arr[i];a=c;c=lcm(a,b);}cout<<c<<endl;}return 0;
}