130道基础OJ编程题之: 29 ~ 38 道
文章目录
- 130道基础OJ编程题之: 29 ~ 38 道
- 0. 昔日OJ编程题:
- 29. BC23 时间转换
- 30. BC24 总成绩和平均分计算
- 31. BC30 KiKi和酸奶
- 32. BC31 发布信息
- 33. BC3 输出学生信息
- 34. BC33 计算平均成绩
- 35. BC34 进制A+B
- 36. BC37 网购
- 37.BC39 争夺前五名
- 38. BC40 竞选社长
- 总结:
- 最后:
OJ技巧
#include <stdio.h>
int main() {
int a, b;
while (scanf("%d %d", &a, &b) != EOF) { // 注意 while 处理多个 case
// 64 位输出请用 printf("%lld") to
printf("%d\n", a + b);
}
return 0;
}
import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int a = in.nextInt();
int b = in.nextInt();
System.out.println(a + b);
}
}
}
0. 昔日OJ编程题:
130道基础OJ编程题之: 1~7道_ChinaRainbowSea的博客-CSDN博客
130道基础OJ编程题之: 8~19 道_ChinaRainbowSea的博客-CSDN博客
130道基础OJ编程题之: 20~28_ChinaRainbowSea的博客-CSDN博客_编程
29. BC23 时间转换
时间转换_牛客题霸_牛客网 (nowcoder.com)
C语言实现:
思路: 已知定秒数 : 0 < seconds < 100000000, 的范围,int 类型足够存下,我们只需要通过秒数得到对应的 划分为对应的小时,秒,分钟:
- 3661秒 / 60 / 60 = 小时
- 3661 / 60 = 61 分钟,61 分钟 % 60 = 1 分钟,前 60 分钟转化为了 1小时,取模
%
60得到剩下的 1 分钟 - 3661 % 60 = 1 秒,前面被 60 取模尽都是 转换为了 小时,分钟,最后剩余的便是 秒了。
#include <stdio.h>
int main()
{
int seconds = 0;
scanf("%d",&seconds);
int h = seconds/60/60; // 小时
int m = seconds/60%60; // 分钟
int s = seconds%60; // 秒
printf("%d %d %d",h,m,s);
return 0;
}
方式二:
#include <stdio.h>
int main()
{
int seconds = 0;
scanf("%d",&seconds);
int h = seconds/ 3600; // 小时
int m = (seconds - h*3600) / 60; // 分钟
int s = seconds - h*3600 - m * 60; // 秒
printf("%d %d %d",h,m,s);
return 0;
}
Java实现:
方式一:
思路: 和上述C语言实现是一样的,这里就不重复讲述了
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int seconds = scanner.nextInt();
int h = seconds / 60 / 60 ; // 小时
int m = seconds / 60 % 60 ; // 分钟
int s = seconds % 60 ; // 秒
System.out.println(h+" "+m+" "+s);
}
}
方式二:
思路: 通过不断转换后的小时,分钟之间的减法得到对应的值
- 3661 / 3660 = 1 小时;
- 3661 - 1(小时) * 3600 = 61 (剩下秒数) / 60 = 分钟
- 3661 - 得到的小时1*3600 - 得到的 1 分钟 * 60 = 剩余的秒数
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int seconds = scanner.nextInt();
int h = seconds / 3600; // 小时
int m = (seconds - h * 3600) / 60 ; // 分钟
int s = seconds - h * 3600 - m * 60 ; // 秒
System.out.println(h+" "+m+" "+s);
}
}
30. BC24 总成绩和平均分计算
总成绩和平均分计算_牛客题霸_牛客网 (nowcoder.com)
C语言实现:
方式一:
思路: 一次性将三个数值,全部输入完毕,注意 double 类型的输入输出格式是 %lf
#include <stdio.h>
int main()
{
double gender1 = 0.0;
double gender2 = 0.0;
double gender3 = 0.0;
scanf("%lf %lf %lf",&gender1,&gender2,&gender3);
double sum = gender1+gender2+gender3;
printf("%.2lf %.2lf",sum,sum/3);
return 0;
}
方式二:
思路: 通过创建一个数组,用于存放输入的成绩的数值,同时计算求和,最后输出;
#include <stdio.h>
int main()
{
double genders[3] = {0};
double sum = 0.0;
for(int i = 0; i < sizeof(genders)/(sizeof(int));i++)
{
scanf("%lf",&genders[i]);
sum += genders[i];
}
printf("%.2lf %.2lf",sum,sum/3);
return 0;
}
Java实现:
思路: 通过创建double 类型的数组存放输入的数值,使用 new
的方式创建数组,可以指定数组的大小。在通过Java当中的 printf
的格式输出,需要注意的是Java当中的 printf 没有 %lf, %ld ,只有%d,%f
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double[] genders = new double[3]; // 创建数组
double sum = 0.0;
for(int i = 0; i < genders.length;i++) {
genders[i] = scanner.nextDouble();
sum += genders[i];
}
System.out.printf("%.2f %.2f",sum,sum/3);
/*
注意在Java当中的 printf 对应的浮点数类型是 %f,没有%lf报错以及 整数类型只有 %d,没有%ld 报错*/
}
}
方式二:
思路: 我们可以使用 String.format(Locale l,String format,Object... args)
的静态方法 替换 printf,格式化对应的字符串,locale 1 参数表示的是: 你想要表示的字符格式 %.2f/%.d 这样的,String format, 表示需要转换的字符串(如果传的是数值会自动转换为字符串),Object…args 可变参数,可以不传参数,但是不要传null,null引用。
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double[] genders = new double[3]; // 创建数组
double sum = 0.0;
for(int i = 0; i < genders.length;i++) {
genders[i] = scanner.nextDouble();
sum += genders[i];
}
System.out.println(String.format("%.2f",sum)+" "+String.format("%.2f",sum/3));
/*
注意在Java当中的 printf 对应的浮点数类型是 %f,没有%lf报错以及 整数类型只有 %d,没有%ld 报错*/
}
}
31. BC30 KiKi和酸奶
KiKi和酸奶_牛客题霸_牛客网 (nowcoder.com)
C语言实现:
思路: 注意是多组输入的方式 我们需要用上 while(scanf("%d %d %d",&n,&h,&m) != EOF)
EOF
表示的文件结束标识,#define EOF (-1)
如果 h 分钟喝完一瓶酸奶,那么 m 分钟就可以喝 m /h 瓶酸奶,但是如果 m / h 有余数(m % h),就说明kiki正在喝一瓶酸奶,但是没有喝光,被喝的这一瓶酸奶也要算上,总的酸奶个数 n - 被喝的酸奶的个数 = 剩下酸奶的个数。
#include<stdio.h>
int main()
{
int n = 0;
int h = 0;
int m = 0;
while(scanf("%d %d %d",&n,&h,&m) != EOF)
{
int sum = 0;
if( m % h > 0 ) // 表示kiki正在喝酸奶,
{
sum = m / h + 1; // 加上kiki正在喝的这瓶酸奶
}
else // 表示kiki不在喝酸奶
{
sum = m / h;
}
printf("%d\n",n - sum);
}
return 0;
}
方式二:
思路: 我们使用while(~scanf("%d %d %d",&n,&h,&m))
替换掉while(scanf("%d %d %d",&n,&h,&m) != EOF)
的使用
补充:
说明: EOF 在 C++ 中表示的是 -1
的意思,同时又是文件内容最后一个内容的结束标志。
所以 EOF 的本质其实是 -1
,而 ~
表示的是取反的意思,while(~scanf(“%d %d %d”,&n,&h,&m))
表达的意思就是: 当scanf 返回的结果是 EOF 我们就将EOF(-1在C语言中非0 的表示真) 取反变成了 0(假),假跳出循环。
#include<stdio.h>
int main()
{
int n = 0;
int h = 0;
int m = 0;
while(~scanf("%d %d %d",&n,&h,&m))
{
int sum = 0;
if( m % h > 0 ) // 表示kiki正在喝酸奶,
{
sum = m / h + 1; // 加上kiki正在喝的这瓶酸奶
}
else // 表示kiki不在喝酸奶
{
sum = m / h;
}
printf("%d\n",n - sum);
}
return 0;
}
Java实现:
思路: 和C语言实现的方式一的思路是一样的,不同的是在Java当中多组输入整数 使用: while(scanner.hasNextInt())
的方式.
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNextInt()) {
int n = scanner.nextInt();
int h = scanner.nextInt();
int m = scanner.nextInt();
int sum = 0;
if(m % h > 0 ) { // kiki正在喝酸奶,没有喝光
sum = m / h +1;
}
else {
sum = m / h; // kiki没有在喝酸奶
}
System.out.println(n-sum);
}
}
}
32. BC31 发布信息
发布信息_牛客题霸_牛客网 (nowcoder.com)
C语言实现:
思路:
#include<stdio.h>
int main()
{
printf("I lost my cellphone!\n");
return 0;
}
java实现:
import java.util.*;
public class Main{
public static void main(String[] args) {
System.out.println("I lost my cellphone!");
}
}
33. BC3 输出学生信息
输出学生信息_牛客题霸_牛客网 (nowcoder.com)
C语言实现:
思路: 注意空格的个数
#include<stdio.h>
int main(){
printf("Name Age Gender\n");//注意四个空格 和换行
printf("---------------------\n");
printf("Jack 18 man\n");//注意五个空格 对齐
return 0;
}
Java实现方法:
import java.util.*;
public class Main{
public static void main(String[] args) {
System.out.println("Name Age Gender");
System.out.println("---------------------");
System.out.println("Jack 18 man");
}
}
34. BC33 计算平均成绩
计算平均成绩_牛客题霸_牛客网 (nowcoder.com)
C语言实现:
思路: 定义一个int数组,通过循环将 5 数值存入到数组中去了。
方式一:
#include<stdio.h>
int main()
{
double sum = 0.0;
int arr[5] = {0};
for(int i = 0; i < 5; i++)
{
scanf("%d",&arr[i]);
sum = arr[i] + sum;
}
printf("%.1lf",sum/5.0);
return 0;
}
Java实现:
思路: 使用Java当中的printf
的格式输入,或者使用:String.format("%.1f",sum/5)
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int[] arrs = new int[5];
double sum = 0.0;
for(int i = 0; i < arrs.length;i++) {
arrs[i] = scanner.nextInt();
sum += arrs[i];
}
// System.out.printf("%.1f",sum/5); // 注意在java当中浮点数的格式输入是 %.f,没有%.2f,整型的格式是%.d没有 %.ld;
// 或者使用
System.out.println(String.format("%.1f",sum/5));
// 注意同理:java当中的:%f,%d 的格式
}
}
35. BC34 进制A+B
进制A+B_牛客题霸_牛客网 (nowcoder.com)
C语言实现:
思路: 十六进制Hexadecimal一般以0x开头,例如0xFF。八进制Octal,一般以0开头,例如07。
首先要理解十进制,十六进制,八进制只是一种数据的表示形式,不是数据的存储形式,它们的存储的都是二进制的。只是将二进制中的数据取出后的表示形式不同而已。具体详细说明,大家可以移步到: 数据是:如何在 ”内存“中的 ”存“ 和 ”取“ 的_ChinaRainbowSea的博客-CSDN博客
不同格式的数据的的输出在C语言中有不同的格式指定,比如:%x
是十六进制格式,%O
就是八进制格式。
不同进制得到数据存放都是补码,直接使用补码交给计算机。
#include<stdio.h>
int main()
{
int num1 = 0;
int num2 = 0;
scanf("%x %o",&num1,&num2);
printf("%d\n",num1+num2);
return 0;
}
Java实现:
思路: 我们先将数值,以字符串的类型读取,注意使用 nextLine(),和next的区别,nextLine()可以读取到空格,next不可以读取到空格,再使用 String.sqlit(" ") 的方法根据“ ”空格将读取到的字符串进行一个分组划分。将分组后的字符串存储到字符串数组中,再通过 Integer.parseInt()的方法将字符串的内容转为需要的进制的格式,十六进制,八进制。
通过 String.substring() 方法将去掉我们从键盘上读取到的 0x十六进制,0八进制的标志去了,通过获取到指定字符指定下标的内容。
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine(); // 注意nextLine和next的不同,next不可以读取到空格,nexttLine()可以读取到空格
String[] sl = str.split(" "); // 将字符串的内容根据" "进行一个分割。并将分组后字符串内容返回到字符串数组中去
// 去除0x,o使用
int a = Integer.parseInt(sl[0].substring(2,sl[0].length()),16);
int b = Integer.parseInt(sl[1].substring(1,sl[1].length()),8);
System.out.println(a+b);
// Integer int类型的包装类,parseInt(输出的数值,输出的格式)
// substring(表示获取到对应下标之间的内容)
}
}
36. BC37 网购
网购_牛客题霸_牛客网 (nowcoder.com)
C语言实现:
思路: 巧妙的设计变量,通过再通过 if 判断语句的方式,改变双11,双12 的变量的折扣,巧妙的使用 falg = 0 (优惠券)*50 后的值,0* 50 = 0;的方式。
注意我们最后的结果是保留两位小数’0.00’,以及商家不会回退钱的。
#include<stdio.h>
int main()
{
double val = 0;
int month = 0;
int day = 0;
int falg = 0;
float discount = 1;
scanf("%lf %d %d %d",&val,&month,&day,&falg);
if(month == 11 && day == 11) // 双11
{
discount = 0.7;
}
if(month == 12 && day == 12) // 双12
{
discount = 0.8;
}
double sum = val*discount-falg*50; // 总和
if(sum <= 0)
{
printf("0.00\n");
}
else
{
printf("%.2lf\n",sum);
}
return 0;
}
Java实现
思路: 和上述C语言实现的方式是一样的思路,需要明白的是,空格
本身就可以最为分割不同输入的格式。
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double val = scanner.nextDouble(); // 价格
int month = scanner.nextInt(); // 月
int day = scanner.nextInt(); // 天
int falg = scanner.nextInt(); // 优惠券
double discount = 0; // 折扣
double sum = 0; // 实际价格
if(11==month && 11 == day) {
discount = 0.7;
}
if(12==month && 12 == day) {
discount = 0.8;
}
sum = val*discount-falg*50;
if(sum <= 0) {
// System.out.printf("0.00\n"); // %d,%f
System.out.println("0.00");
}
else{
// System.out.printf("%.2f",sum);
// 或者使用
System.out.println(String.format("%.2f",sum));
}
}
}
37.BC39 争夺前五名
争夺前五名_牛客题霸_牛客网 (nowcoder.com)
C语言实现:
思路: 这里由于是C语言不支持,arr[n] 数组大小变量的定义,所以我们一开始就将数组定义为题目中的最大同学的个数。通过for循环为数组多个数值赋值,再通过简单的冒泡排序将我们的同学的成绩进行一个降序(把数值大的变量放到数组的后面)的排序过程,排序好后,再遍历数组获取到前我五的数值内容,
注意冒泡排序的越界的的问题。下标访问的大小。
#include<stdio.h>
int main()
{
int arr[50] = {0};
int n = 0;
scanf("%d",&n);
for(int i = 0; i<n; i++)
{
scanf("%d",&arr[i]);
}
// 冒泡排序,最后一个不用排序,升序
for(int i = 0; i < n-1;i++)
{
for(int j = 1; j < n-i;j++) // 这里我们使用j = 1,防止n-i数组越界的访问.
{ // 小于的往后移动
if(arr[j-1] < arr[j])
{
int temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
}
}
}
// 排序显示 前五个的成绩
for(int i = 0; i < 5; i++)
{
printf("%d ",arr[i]);
}
return 0;
}
Java实现:
思路: 和上述C语言实现的方式是一样的,这就不多介绍了。
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] arrs = new int[n];
for(int i = 0; i < arrs.length;i++){
arrs[i] = scanner.nextInt();
}
// 冒泡排序,降序(数值小的放到后面)
for(int i = 0; i < arrs.length-1;i++) {
for(int j = 1; j < arrs.length-i;j++) { // 注意是从下标 1 开始的,
if(arrs[j-1] < arrs[j]) { // 前面小的数值放后
int temp = arrs[j];
arrs[j] = arrs[j-1];
arrs[j-1] = temp;
}
}
}
// 排序结束,取出前5个成绩
for(int i = 0; i < 5; i++) {
System.out.print(arrs[i]+" ");
}
}
}
38. BC40 竞选社长
竞选社长_牛客题霸_牛客网 (nowcoder.com)
C语言实现:
方式一:
思路: 我们通过创建定义一个字符数组,因为在C语言当中没有字符串类型,所以我们定义字符数组存储字符串,
再通过循环,将存入数组中的内容逐一取出,并判断是否等于 ‘A’/ ‘B’ 符合条件,计数,最后循环结束(注意需要结束的条件是 0 && 以及 EOF(文件结束标志)),判断各个的计数结果,输出内容。
#include<stdio.h>
int main()
{
char arrs[100] = {0};
gets(arrs); // 读取字符串
int i = 0;
int countA = 0;
int countB = 0;
while(arrs[i]!=0 && arrs[i] !=EOF)
{
if('A' == arrs[i])
{
countA++;
}
if('B' == arrs[i])
{
countB++;
}
i++;
}
if( countA > countB)
{
printf("A\n");
}
else if(countA == countB)
{
printf("E\n");
}
else
{
printf("B\n");
}
return 0;
}
方式二:
思路: 配合使用循环使用上 getchar()
获取到对应的键盘上多个输入的值,每次读取到一个数值的内容再,进行一个判断和计数。最后通过计数的结果进行一个判断
#include<stdio.h>
int main()
{
char c = 0;
int countA = 0;
int countB = 0;
while( (c = getchar()) != '0')
{
if('A' == c)
{
countA++;
}
if('B' == c)
{
countB++;
}
}
if(countA < countB)
{
printf("B\n");
}
else if(countB == countA)
{
printf("E\n");
}
else
{
printf("A\n");
}
return 0;
}
方式三:
思路: 只是定义一个变量对数据进行一个进行一个判断,通过变向的使用 ++自增,–自减的方式对,进行一个计数
#include<stdio.h>
int main()
{
int flag = 0;
char c = 0;
while((c = getchar()) != '0' && c != EOF)
{
if('A' == c)
{
flag++;
}
if('B' == c)
{
flag--;
}
}
if(flag > 0 ) // 表示 A 字符多了
{
printf("A\n");
}
else if(0 == flag) // 表示 A 和 B 的数据同样多
{
printf("E\n");
}
else
{
printf("B\n");
}
return 0;
}
java实现:
方式一:
思路: 通过String.charAt() 的方法获取到指定字符串下标的字符内容,并进行一个判断,符合结果的进行一个计数。该方法的具体文档如下:
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.next();
int countA = 0;
int countB = 0;
for(int i = 0; i < str.length();i++) {
if(str.charAt(i) == 'A') { // 取出下标为i的字符串的字符,并判断
countA++;
}
if('B' == str.charAt(i)) {
countB++;
}
}
if( countA > countB) {
System.out.println("A");
} else if(countA == countB) {
System.out.println("E");
} else {
System.out.println("B");
}
}
}
方式二:
思路: 使用String.replace()
将字符串中的内容替换成我们指定的内容
int countA = str.replace("B", "").length()-1;
将字符串的 B 替换成字符串 “ ” 没有的字符,那么剩下的不就全是 A 的字符了吗。这时候我们再求其字符串的长度,再额外减 - 1 ,去掉 包含的 0 字符。就是 A 在该字符串的个数了
int countB = str.replace("A","").length()-1
将字符串的 A 替换成没有的字符 “” ,那么剩下的不就全是 B 字符串了(包含 0 ),同样这个时候我们再求字符串的长度,再额外减 -1 ,去掉包含的 0 字符,就是 B 在该字符串的个数了。
该方法的具体文档内容如下:
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.next();
int countA = str.replace("B", "").length()-1;
int countB = str.replace("A","").length()-1; // 字符串中的 A 替换成"" 空字符,剩余的不就是的B了吗,再求返回的字符串长度 -1 去掉 0
if( countA > countB){
System.out.println("A");
} else if( countA == countB) {
System.out.println("E");
} else {
System.out.println("B");
}
}
}
总结:
- C语言中的多个输入的值,EOF 表示文档的结束标志,while(scanf() != EOF) ,以及 while(~scanf())的意思(表示EOF(-1) 取反为 0 (假))
- Java当中的多组数据的输入
while (scanner.hasNextInt()
以及 next 与 nextLine 的区别: next()读取不到空格,nextLine()可以读取到空格- 在Java当中使用
System.out.printf(%d,%f)
以及String.format("%d,%f",数值()转换为字符串)
表示格式输出,注意在Java当中是没有 %ld,%lf 的。- C语言中的读取多个字符串
gets(arr)
- 在java 当中的
String.charAt()
获取到指定下标的字符串的内容,以及str.replace("A","")
将字符串中的指定字符替换为指定的字符- 注意冒泡排序,不要越界访问了。
- java当中的
String.sqlit(" ")
对字符串的内容进行一划分,返回字符串数组。substring(2,string.length)
通过对应字符串下标开始,获取到指定长度的字符串。Integer.parseInt(String str,"%d/%f")
的方法将字符串的内容转为需要的进制的格式,十六进制,八进制。
最后:
限于自身水平,其中存在的错误,希望大家可以多多指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见 !!!