​  前天报名了CCF CSP认证考试,用了两天时间,好不容易把官网提供的历次考试真题做完了。CSP认证考试一共5道题目,难度依次递增,考试时长4小时。做完了最简单的第1题之后发现,确实比计算机二级考试水准要高得多。

图片说明

CCF CSP简介

以下关于CCF的介绍来自官网CCF计算机职业资格认证

  CCF计算机软件能力认证 Certified Software Professional)是中国计算机学会(CCF)联合华为、360、滴滴等十余家知名IT企业以及清华、北航、国防科大等15所著名高校于2014年推出CCF CSP(计算机软件能力)认证标准,用于评价业界人士的计算机软件能力。目前,CCF已成功举办17次CSP认证,来自全国400余所单位的109819人参加了认证。

试题编号: 201312-1_出现次数最多的数

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  给定n个正整数,找出它们中出现次数最多的数。如果这样的数有多个,请输出其中最小的一个。
输入格式
  输入的第一行只有一个正整数n(1 ≤ n ≤ 1000),表示数字的个数。
  输入的第二行有n个整数s1, s2, …, sn (1 ≤ si ≤ 10000, 1 ≤ i ≤ n)。相邻的数用空格分隔。
输出格式
  输出这n个次数中出现次数最多的数。如果这样的数有多个,输出其中最小的一个。
样例输入
6
10 1 10 20 30 20
样例输出
10

import java.util.Scanner;

public class 出现次数最多的数 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int ans = 0;
int temp = 0;
int count[] = new int[n];
int arr[] = new int[10001]; // arr是统计各个数个数的数组,x出现一次,则arr[x]++
for (int i = 0; i < n; i++) {
    count[i] = sc.nextInt();
    arr[count[i]]++;
}
for (int i = 1; i <= 10000; i++) {
    if (arr[i] > temp) {
    ans = i; //如果arr[i]>temp,则将次数最多的数为i;遍历整个数组,i变化的同时,不断刷新temp和ans的值
    temp = arr[i];
    }
}
System.out.println(ans);
}
}

试题编号: 201403-1_相反数

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  有 N 个非零且各不相同的整数。请你编一个程序求出它们中有多少对相反数(a 和 -a 为一对相反数)。
输入格式
  第一行包含一个正整数 N。(1 ≤ N ≤ 500)。
  第二行为 N 个用单个空格隔开的非零整数,每个数的绝对值不超过1000,保证这些整数各不相同。
输出格式
  只输出一个整数,即这 N 个数中包含多少对相反数。
样例输入
5
1 2 3 -1 -2
样例输出
2

import java.util.HashSet;
import java.util.Scanner;

public class 相反数 {

    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    HashSet<Integer> set = new HashSet<Integer>();
    for (int i = 0; i < n; i++) {
        set.add(Math.abs(sc.nextInt()));
    }
//如果对所有的数取绝对值,那么相反数必定是两个相等的正整数,利用Set容器对数据
//进行去重,就可以去掉重复数据,相反数的对数 = 初始数据数量 — Set的容量
    System.out.println(n - set.size());
    }
}

试题编号: 201409-1_相邻数对

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  给定n个不同的整数,问这些数中有多少对整数,它们的值正好相差1。
输入格式
  输入的第一行包含一个整数n,表示给定整数的个数。
  第二行包含所给定的n个整数。
输出格式
  输出一个整数,表示值正好相差1的数对的个数。
样例输入
6
10 2 6 3 7 8
样例输出
3
样例说明
  值正好相差1的数对包括(2, 3), (6, 7), (7, 8)。
评测用例规模与约定
  1<=n<=1000,给定的整数为不超过10000的非负整数。

import java.util.Scanner;

public class 相邻数对 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int flag = 0;
int count[] = new int[n];
for (int i = 0; i < n; i++) {
    count[i] = sc.nextInt();
}
for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j++) {
    if (Math.abs(count[i] - count[j]) == 1)
        flag++;
   /*和冒泡排序法一样,用count中的每一个元素和其余n-1个元素去做差,如果差的绝对值为1,说明是一个相邻数对,flag加1*/
    }
}
System.out.println(flag);
}
}

试题编号:201412-1_门禁系统

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  涛涛最近要负责图书馆的管理工作,需要记录下每天读者的到访情况。每位读者有一个编号,每条记录用读者的编号来表示。给出读者的来访记录,请问每一条记录中的读者是第几次出现。
输入格式
  输入的第一行包含一个整数n,表示涛涛的记录条数。
  第二行包含n个整数,依次表示涛涛的记录中每位读者的编号。
输出格式
  输出一行,包含n个整数,由空格分隔,依次表示每条记录中的读者编号是第几次出现。
样例输入
5
1 2 1 1 3
样例输出
1 1 2 3 1
评测用例规模与约定
  1≤n≤1,000,读者的编号为不超过n的正整数。

import java.util.Scanner;

public class 门禁系统 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int count[] = new int[n];
int times[] = new int[n];
for (int i = 0; i < n; i++) {
    count[i] = sc.nextInt();
    times[count[i]]++;
    System.out.print(times[count[i]] + " ");
/*输入一个数,另一个数组相应位置加1,然后输出这个位置的数,也就是输入数据出现的次数*/
}
}
}

试题编号: 201503-1_图像旋转

时间限制: 5.0s
内存限制: 256.0MB
问题描述:
问题描述
  旋转是图像处理的基本操作,在这个问题中,你需要将一个图像逆时针旋转90度。
  计算机中的图像表示可以用一个矩阵来表示,为了旋转一个图像,只需要将对应的矩阵旋转即可。
输入格式
  输入的第一行包含两个整数n, m,分别表示图像矩阵的行数和列数。
  接下来n行每行包含m个整数,表示输入的图像。
输出格式
  输出m行,每行包含n个整数,表示原始矩阵逆时针旋转90度后的矩阵。
样例输入
2 3
1 5 3
3 2 4
样例输出
3 4
5 2
1 3
评测用例规模与约定
  1 ≤ n, m ≤ 1,000,矩阵中的数都是不超过1000的非负整数。

import java.util.Scanner;

public class 图像旋转 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
int arr[][] = new int[n][m];

for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
    arr[i][j] = sc.nextInt();
    }
}
for (int i = m - 1; i >= 0; i--) {
    for (int j = 0; j < n; j++) {
    System.out.print(arr[j][i] + " ");
       /*旋转90度,可以直接竖着一列一列地输出,因为逆时针旋转,因此列的最大值变成了行的最小值,并且n行m列变成m行n列,列要从 最大索引开始输出,行和以前一样*/
    }
    System.out.println();
}
}
}

试题编号: 201509-1_数列分段

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  给定一个整数数列,数列中连续相同的最长整数序列算成一段,问数列***有多少段?
输入格式
  输入的第一行包含一个整数n,表示数列中整数的个数。
  第二行包含n个整数a1, a2, …, an,表示给定的数列,相邻的整数之间用一个空格分隔。
输出格式
  输出一个整数,表示给定的数列有多个段。
样例输入
8
8 8 8 0 12 12 8 0
样例输出
5
样例说明
  8 8 8是第一段,0是第二段,12 12是第三段,倒数第二个整数8是第四段,最后一个0是第五段。
评测用例规模与约定
  1 ≤ n ≤ 1000,0 ≤ ai ≤ 1000。

import java.util.Scanner;

public class 数列分段 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int temp = 1;
int arr[] = new int[n];

for (int i = 0; i < n; i++) {
    arr[i] = sc.nextInt();
}

for (int j = 1; j < n; j++) {
    if (arr[j - 1] != arr[j])
    temp++;
}
    /*因为长度至少为1,因此至少可以分1段,从索引为1开始判断,如果和前一个数值相等则不处理,如果不相等,则给temp加1*/
System.out.println(temp);
}
}

试题编号: 201512-1_数位之和

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  给定一个十进制整数n,输出n的各位数字之和。
输入格式
  输入一个整数n。
输出格式
  输出一个整数,表示答案。
样例输入
20151220
样例输出
13
样例说明
  20151220的各位数字之和为2+0+1+5+1+2+2+0=13。
评测用例规模与约定
  所有评测用例满足:0 ≤ n ≤ 1000000000。

import java.util.Scanner;

public class 数位之和 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int sum = 0;
String str = Integer.toString(n);
for (int i = 0; i < str.length(); i++) {
    sum += str.charAt(i) - '0';
}
    /*利用java内置的toString函数将证书变为字符串,然后挨个取出字符串中每一个字符,此时他们进行加减是ASCII值之间的运算,只需要给每个字符减去字符‘0’,即可将其变为0——9的整数,然后再累加即可*/
System.out.println(sum);
}
}

试题编号: 201604-1_折点计数

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  给定n个整数表示一个商店连续n天的销售量。如果某天之前销售量在增长,而后一天销售量减少,则称这一天为折点,反过来如果之前销售量减少而后一天销售量增长,也称这一天为折点。其他的天都不是折点。如下图中,第3天和第6天是折点。

img

  给定n个整数a1, a2, …, an表示销售量,请计算出这些天总共有多少个折点。
  为了减少歧义,我们给定的数据保证:在这n天中相邻两天的销售量总是不同的,即ai-1≠ai。注意,如果两天不相邻,销售量可能相同。
输入格式
  输入的第一行包含一个整数n。
  第二行包含n个整数,用空格分隔,分别表示a1, a2, …, an。
输出格式
  输出一个整数,表示折点出现的数量。
样例输入
7
5 4 1 2 3 6 4
样例输出
2
评测用例规模与约定
  所有评测用例满足:1 ≤ n ≤ 1000,每天的销售量是不超过10000的非负整数。

import java.util.Scanner;

public class 折点计数 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int a[] = new int[n];
for (int i = 0; i < n; i++) {
    a[i] = sc.nextInt();
}
int flag = 0;
for (int i = 1; i < n - 1; i++) {
    if ((a[i] > a[i - 1] && a[i] > a[i + 1]) || (a[i] < a[i - 1] && a[i] < a[i + 1]))
    flag++;
/*在转折点两侧的数,要么都比a[i]大,要么都比a[i]小,当符合这个条件时,计数器flag加1*/
}
System.out.println(flag);
}
}

试题编号: 201609-1_最大波动

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  小明正在利用股票的波动程度来研究股票。小明拿到了一只股票每天收盘时的价格,他想知道,这只股票连续几天的最大波动值是多少,即在这几天中某天收盘价格与前一天收盘价格之差的绝对值最大是多少。
输入格式
  输入的第一行包含了一个整数n,表示小明拿到的收盘价格的连续天数。
  第二行包含n个正整数,依次表示每天的收盘价格。
输出格式
  输出一个整数,表示这只股票这n天中的最大波动值。
样例输入
6
2 5 5 7 3 5
样例输出
4
样例说明
  第四天和第五天之间的波动最大,波动值为|3-7|=4。
评测用例规模与约定
  对于所有评测用例,2 ≤ n ≤ 1000。股票每一天的价格为1到10000之间的整数。

import java.util.Scanner;

public class 最大波动 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[] = new int[n];
for (int i = 0; i < n; i++) {
    arr[i] = sc.nextInt();
}
int max = Math.abs(arr[0] - arr[1]);
for (int j = 1; j < n - 1; j++) {
    if (Math.abs(arr[j] - arr[j + 1]) > max)
    max = Math.abs(arr[j] - arr[j + 1]);
    /*最大波动指的是相邻两个数之间最大的差值,因此先设最大差值为第0个和第1个元素之间的差值,然后遍历数组,比较相邻两个数之间的差值和设定的最大差值的大小关系,不断地更新最大差值即可得出整个数组的相邻元素最大差值*/
}
System.out.println(max);
}
}

试题编号: 201612-1_中间数

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  在一个整数序列a1, a2, …, an中,如果存在某个数,大于它的整数数量等于小于它的整数数量,则称其为中间数。在一个序列中,可能存在多个下标不相同的中间数,这些中间数的值是相同的。
  给定一个整数序列,请找出这个整数序列的中间数的值。
输入格式
  输入的第一行包含了一个整数n,表示整数序列中数的个数。
  第二行包含n个正整数,依次表示a1, a2, …, an。
输出格式
  如果约定序列的中间数存在,则输出中间数的值,否则输出-1表示不存在中间数。
样例输入
6
2 6 5 6 3 5
样例输出
5
样例说明
  比5小的数有2个,比5大的数也有2个。
样例输入
4
3 4 6 7
样例输出
-1
样例说明
  在序列中的4个数都不满足中间数的定义。
样例输入
5
3 4 6 6 7
样例输出
-1
样例说明
  在序列中的5个数都不满足中间数的定义。
评测用例规模与约定
  对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ ai ≤ 1000。

import java.util.Arrays;
import java.util.Scanner;

public class 中间数 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int left = 0;
int left1 = 0;
int right = 0;
int right1 = 0;
int arr[] = new int[n];
for (int i = 0; i < n; i++) {
    arr[i] = sc.nextInt();
}
Arrays.sort(arr);
    /*先给数组排序,如果存在中间数,那么他已定位于有序数组的中间位置,取出排序后中间位置的数,计算这个数之前的小于他的数的个数,以及这个数之后的大于他的数的个数,比较两个数值是否相等即可。因为数组长度可能为奇数,与可能为偶数,因此需要分开判断*/

    /*如果数组长度为奇数*/
if (n % 2 == 0) {

    if (arr[n / 2] != arr[n / 2 - 1]) {
    for (int i = 0; i < n; i++) {
        if (arr[i] < arr[n / 2])
        left++;
        if (arr[i] > arr[n / 2])
        right++;

    }

    for (int i = 0; i < n; i++) {
        if (arr[i] < arr[n / 2 - 1])
        left1++;
        if (arr[i] > arr[n / 2 - 1])
        right1++;
    }

    if (left == right)
        System.out.println(arr[n / 2]);
    else
        System.out.println("-1");

    if (left1 == right1)
        System.out.println(arr[n / 2 - 1]);
    if (left1 == right1 && left != right)
        /* 这里必须判断arr[n/2]是否为中间数,如果不是,那么已经有一个-1输出,这里就不需要输出了*/
        System.out.println("-1");

    } else {
    for (int i = 0; i < n; i++) {
        if (arr[i] < arr[n / 2])
        left++;
        if (arr[i] > arr[n / 2])
        right++;

    }
    if (left == right)
        System.out.println(arr[n / 2]);
    else
        System.out.println("-1");
    }

}
/*如果数组长度为奇数*/
if (n % 2 == 1) {
    for (int i = 0; i < n; i++) {
    if (arr[i] < arr[n / 2])
        left++;
    if (arr[i] > arr[n / 2])
        right++;
    }
    if (left == right)
    System.out.println(arr[n / 2]);
    else
    System.out.println("-1");
}

}
}

试题编号: 201703-1_分蛋糕

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  小明今天生日,他有n块蛋糕要分给朋友们吃,这n块蛋糕(编号为1到n)的重量分别为a1, a2, …, an。小明想分给每个朋友至少重量为k的蛋糕。小明的朋友们已经排好队准备领蛋糕,对于每个朋友,小明总是先将自己手中编号最小的蛋糕分给他,当这个朋友所分得蛋糕的重量不到k时,再继续将剩下的蛋糕中编号最小的给他,直到小明的蛋糕分完或者这个朋友分到的蛋糕的总重量大于等于k。
  请问当小明的蛋糕分完时,总共有多少个朋友分到了蛋糕。
输入格式
  输入的第一行包含了两个整数n, k,意义如上所述。
  第二行包含n个正整数,依次表示a1, a2, …, an。
输出格式
  输出一个整数,表示有多少个朋友分到了蛋糕。
样例输入
6 9
2 6 5 6 3 5
样例输出
3
样例说明
  第一个朋友分到了前3块蛋糕,第二个朋友分到了第4、5块蛋糕,第三个朋友分到了最后一块蛋糕。
评测用例规模与约定
  对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ k ≤ 10000,1 ≤ ai ≤ 1000。

import java.util.Scanner;

public class 分蛋糕 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
int cakesum = 0;
int sum = 0;
int people = 0;
int sum1 = 0;
int cake[] = new int[n];
for (int i = 0; i < n; i++) {
    cake[i] = sc.nextInt();
    cakesum += cake[i];
    /*在输入蛋糕数量的同时,计算出蛋糕总数量*/
}
for (int i = 0; i < n; i++) {
    sum += cake[i];
    /*将蛋糕数量加起来,当数量大于或者等于设定的值,说明可以分一个人*/
    if (sum >= k) {
    sum1 += sum;
      /*并且将分出去的蛋糕总数记录下来*/
    people++;
    sum = 0;
      /*分给一个人后,计数器清零*/
    }
}
if (sum1 == cakesum)
    System.out.println(people);
else
    System.out.println(people + 1);
    /*如果分出去的蛋糕等于原有蛋糕总数,说明刚好分完;如果不等于,说明剩下了一些蛋糕,并且剩下的蛋糕不够分给一个人。根据题意,这里剩下的蛋糕还可以分给一个人,因此人数people加1*/
}
}

试题编号: 201709-1_打酱油

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  小明带着N元钱去买酱油。酱油10块钱一瓶,商家进行促销,每买3瓶送1瓶,或者每买5瓶送2瓶。请问小明最多可以得到多少瓶酱油。
输入格式
  输入的第一行包含一个整数N,表示小明可用于买酱油的钱数。N是10的整数倍,N不超过300。
输出格式
  输出一个整数,表示小明最多可以得到多少瓶酱油。
样例输入
40
样例输出
5
样例说明
  把40元分成30元和10元,分别买3瓶和1瓶,其中3瓶送1瓶,共得到5瓶。
样例输入
80
样例输出
11
样例说明
  把80元分成30元和50元,分别买3瓶和5瓶,其中3瓶送1瓶,5瓶送2瓶,共得到11瓶。

import java.util.Scanner;

public class 打酱油 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int a = 0;
int b = 0;
int c = 0;
if (n <= 20)
    System.out.println(n / 10);
else if (n > 20 && n < 50)
    System.out.println((n - 30) / 10 + 4);
else {
    a = n / 50;
    b = (n - a * 50) / 30;
    c = (n - a * 50 - b * 30) / 10;
    System.out.println(a * 7 + b * 4 + c);
    /*30元买4瓶,平均7.5元一瓶;50元买7瓶,平均7.1元一瓶,因此如果钱数超过50,首先按50块的买,然后按30块买,剩下的按10块的买。因此先将钱数除以50,再用剩下的钱数除以30,再用剩下的除以10,然后用50的个数乘7,用30的个数乘4,加上10的个数,就是能买到的最多的酱油瓶数*/
}
}
}

试题编号: 201712-1_最小差值

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  给定n个数,请找出其中相差(差的绝对值)最小的两个数,输出它们的差值的绝对值。
输入格式
  输入第一行包含一个整数n。
  第二行包含n个正整数,相邻整数之间使用一个空格分隔。
输出格式
  输出一个整数,表示答案。
样例输入
5
1 5 4 8 20
样例输出
1
样例说明
  相差最小的两个数是5和4,它们之间的差值是1。
样例输入
5
9 3 6 1 3
样例输出
0
样例说明
  有两个相同的数3,它们之间的差值是0.
数据规模和约定
  对于所有评测用例,2 ≤ n ≤ 1000,每个给定的整数都是不超过10000的正整数。

import java.util.Arrays;
import java.util.Scanner;

public class 最小差值 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int count[] = new int[n];
for (int i = 0; i < n; i++) {
    count[i] = sc.nextInt();
}
Arrays.sort(count);
int min = Math.abs(count[0] - count[1]);
for (int i = 1; i < n - 1; i++) {
    int temp = Math.abs(count[i] - count[i + 1]);
    if (temp < min)
    min = temp;
    /*如果直接算某个数和其他数的差值,将会是O(N*N)的复杂度,而如果先进行排序,只需要从头到尾一次遍历,复杂度为O(n),因此先给数组排序。将count[0]和count[1]的差值定为最小值,然后遍历整个数组,将两个数的差值和最小值比较,不断地更新最小值即可*/
}
System.out.println(min);
}
}

试题编号: 201803-1_跳一跳

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  近来,跳一跳这款小游戏风靡全国,受到不少玩家的喜爱。
  简化后的跳一跳规则如下:玩家每次从当前方块跳到下一个方块,如果没有跳到下一个方块上则游戏结束。
  如果跳到了方块上,但没有跳到方块的中心则获得1分;跳到方块中心时,若上一次的得分为1分或这是本局游戏的第一次跳跃则此次得分为2分,否则此次得分比上一次得分多两分(即连续跳到方块中心时,总得分将+2,+4,+6,+8...)。
  现在给出一个人跳一跳的全过程,请你求出他本局游戏的得分(按照题目描述的规则)。
输入格式
  输入包含多个数字,用空格分隔,每个数字都是1,2,0之一,1表示此次跳跃跳到了方块上但是没有跳到中心,2表示此次跳跃跳到了方块上并且跳到了方块中心,0表示此次跳跃没有跳到方块上(此时游戏结束)。
输出格式
  输出一个整数,为本局游戏的得分(在本题的规则下)。
样例输入
1 1 2 2 2 1 1 2 2 0
样例输出
22
数据规模和约定
  对于所有评测用例,输入的数字不超过30个,保证0正好出现一次且为最后一个数字。

import java.util.Scanner;

public class 跳一跳 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = 1;
int arr[] = new int[30];
int index = 0;
while (num != 0 && index < 30) {
    num = sc.nextInt();
    arr[index] = num;
    index++;
}
/*
 * 这一段代码是因为没有明确的给出步数,因此将步数定为可输入的最大值——30。
 * 然后当输入不为0并且在数组长度范围内时可以连续输入,如果输入10个数,实际上只记录前9个,
 * 因为最后一个数必定是0,没有被计入到数组中,但是没有被赋值的其他元素初值也为0,因此这里不用处理。
 * while(num != 0 && index <30) 当输入开始后,这个判断条件中的num其实是键盘输入 的值sc.nextInt();
 * 并不是定义的初始值1.
 */
int sum = 0; // 纪录总得分
int flag = 0; // 计数器纪录2的个数
for (int i = 0; i < 30; i++) {
    if (arr[i] == 0)
    sum += 0;
    if (arr[i] == 1)
    sum += 1;
    if (arr[i] == 2) {
    flag++;
    /*
     * 如果为2,flag先加1,此时sum+=2*1,然后如果下一个数字还是2,flag再次加1, 此时sum+=2*2,如果
     * 第三个数不等于2,那么 if(arr[i] == 2 && arr[i + 1] != 2) 判断条件生效,清空计数器,准备
     * 下一次计数。
     */
    sum += 2 * flag;
    }
    if (arr[i] == 2 && arr[i + 1] != 2)
    flag = 0;
    // 如果连续的2到这里突然变成了其他,而则计数器清零
}
System.out.println(sum);
}
}

试题编号: 201809-1_卖菜

时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  在一条街上有n个卖菜的商店,按1至n的顺序排成一排,这些商店都卖一种蔬菜。
  第一天,每个商店都自己定了一个价格。店主们希望自己的菜价和其他商店的一致,第二天,每一家商店都会根据他自己和相邻商店的价格调整自己的价格。具体的,每家商店都会将第二天的菜价设置为自己和相邻商店第一天菜价的平均值(用去尾法取整)。
  注意,编号为1的商店只有一个相邻的商店2,编号为n的商店只有一个相邻的商店n-1,其他编号为i的商店有两个相邻的商店i-1和i+1。
  给定第一天各个商店的菜价,请计算第二天每个商店的菜价。
输入格式
  输入的第一行包含一个整数n,表示商店的数量。
  第二行包含n个整数,依次表示每个商店第一天的菜价。
输出格式
  输出一行,包含n个正整数,依次表示每个商店第二天的菜价。
样例输入
8
4 1 3 1 6 5 17 9
样例输出
2 2 1 3 4 9 10 13
数据规模和约定
  对于所有评测用例,2 ≤ n ≤ 1000,第一天每个商店的菜价为不超过10000的正整数。

import java.util.Scanner;

public class 卖菜 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int price[] = new int[n];
int newprice[] = new int[n];
for (int i = 0; i < n; i++) {
    price[i] = sc.nextInt();
}
for (int i = 0; i < n; i++) {
    if (i == 0)
    newprice[i] = (price[i] + price[i + 1]) / 2;
    else if (i == n - 1)
    newprice[i] = (price[i - 1] + price[i]) / 2;
    else
    newprice[i] = (price[i - 1] + price[i] + price[i + 1]) / 3;
/*第0个元素和第n-1个元素只有一个相邻的数,因此相加除以2;其他的都有两个相邻的数,将他们加起来除以3即可*/
    System.out.print(newprice[i] + " ");
}
}
}

试题编号: 201812-1_小明上学

时间限制: 1.0s
内存限制: 512.0MB
问题描述:
题目背景
  小明是汉东省政法大学附属中学的一名学生,他每天都要骑自行车往返于家和学校。为了能尽可能充足地睡眠,他希望能够预计自己上学所需要的时间。他上学需要经过数段道路,相邻两段道路之间设有至多一盏红绿灯。
  京州市的红绿灯是这样工作的:每盏红绿灯有红、黄、绿三盏灯和一个能够显示倒计时的显示牌。假设红绿灯被设定为红灯 r 秒,黄灯 y 秒,绿灯 g 秒,那么从 0 时刻起,[0,r) 秒内亮红灯,车辆不许通过;[r, r+g) 秒内亮绿灯,车辆允许通过;[r+g, r+g+y) 秒内亮黄灯,车辆不许通过,然后依次循环。倒计时的显示牌上显示的数字 l(l > 0)是指距离下一次信号灯变化的秒数。
问题描述
  一次上学的路上,小明记录下了经过每段路的时间,和各个红绿灯在小明到达路口时的颜色和倒计时秒数。希望你帮忙计算此次小明上学所用的时间。
输入格式
  输入的第一行包含空格分隔的三个正整数 r、y、g,表示红绿灯的设置。这三个数均不超过 106。
  输入的第二行包含一个正整数 n(n ≤ 100),表示小明总共经过的道路段数和看到的红绿灯数目。
  接下来的 n 行,每行包含空格分隔的两个整数 k、t。k=0 表示经过了一段道路,耗时 t 秒,此处 t 不超过 106;k=1、2、3 时,分别表示看到了一个红灯、黄灯、绿灯,且倒计时显示牌上显示的数字是 t,此处 t 分别不会超过 r、y、g。
输出格式
  输出一个数字,表示此次小明上学所用的时间。
样例输入
30 3 30
8
0 10
1 5
0 11
2 2
0 6
0 3
3 10
0 3
样例输出
70
样例说明
  小明先经过第一段道路,用时 10 秒,然后等待 5 秒的红灯,再经过第二段道路,用时 11 秒,然后等待 2 秒的黄灯和 30 秒的红灯,再经过第三段、第四段道路,分别用时6、3秒,然后通过绿灯,再经过最后一段道路,用时 3 秒。共计 10 + 5 + 11 + 2 + 30 + 6 + 3 + 3=70 秒。
评测用例规模与约定
  测试点 1, 2 中不存在任何信号灯。
  测试点 3, 4 中所有的信号灯在被观察时均为绿灯。
  测试点 5, 6 中所有的信号灯在被观察时均为红灯。
  测试点 7, 8 中所有的信号灯在被观察时均为黄灯。
  测试点 9, 10 中将出现各种可能的情况。

import java.util.Scanner;

public class 小明上学 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int r = sc.nextInt(); // 红灯时长
int y = sc.nextInt(); // 黄灯时长
int g = sc.nextInt(); // 绿灯时长
int count = sc.nextInt(); // 道路段数
int sum = 0;// 时间总数
int time[][] = new int[count][2];
for (int i = 0; i < count; i++) {
    for (int j = 0; j < 2; j++) {
    time[i][j] = sc.nextInt();
    }
}
for (int i = 0; i < count; i++) {
    if (time[i][0] == 0)
    sum += time[i][1];
    if (time[i][0] == 1)
    sum += time[i][1];
    if (time[i][0] == 2)
    sum += time[i][1]+r;
    if (time[i][0] == 3)
    sum += 0;
    /*0代表没有红绿灯;1代表红灯r, 2代表黄灯y ,3代表绿灯g,当状态为0或者1,直接加上后面的秒数;当状态为2,除了要加上后面表示的黄灯时间外,还需要加上一个完整的红灯时间;当状态为3,不需要处理,因为绿灯亮多少秒不影响他走路。只要是绿灯就可以通过。*/
}
System.out.println(sum);
}
}

试题编号: 201903-1_小中大

时间限制: 1.0s
内存限制: 512.0MB
[题目背景]
在数据分析中,最小值最大值以及中位数是常用的统计信息。
[题目描述]
  老师给了你n个整数组成的测量数据,保证有序( 可能为升序或降序),可能存在重复的数据。请统计出这组测量数据中的最大值、中位数以及最小值,并按照从大到小的顺序输出这三个数。
[输入格式]
从标准输入读入数据。
  第一行输入-一个整数n,在第二行中存在n个有序的整数,表示测量数据,可能为升序或降序排列,可能存在连续多个整数相等,整数与整数之间使用空格隔开。
[输出格式]
输出到标准输出。
  包含一行,包括最大值、中位数以及最小值共三个数,并按照从大到小的顺序输出。数据与数据之间使用空格隔开。对于整数请直接输出整数,对于可能出现的分数,请输出四舍五入保留1位小数的结果。

[样例1输入]
3
-12 4
[样例1输出]
42-1
[样例1解释]
4为最大值,2为中位数,-1为最小值。
[样例2输入]
4
-2 -1 3 4

[子任务]
图片说明

import java.util.Scanner;

public class 小中大 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int count[] = new int[n];
for (int i = 0; i < n; i++) {
    count[i] = sc.nextInt();
}
int max = 0;
int min = 0;
double mid = 0;
if (count[0] > count[n - 1]) {
    max = count[0];
    min = count[n - 1];
} else {
    min = count[0];
    max = count[n - 1];
}
    if (n % 2 == 0)
    mid = (count[n / 2] + count[n / 2 - 1]) / 2.0;
else
    mid = count[n / 2];
  /*这里需要注意,arr中每个元素都为整数,但是mid却有可能为小数。因此mid定义时要定义为浮点类型,否则在进行中位数计算是会都是精度。当arr[n/2]+arr[n/2-1]为奇数时,得出的答案并不是X.5,因此除数应该为2.0*/  
System.out.print(max + " ");
if ((int) mid == mid)
    System.out.print((int) mid + " ");
else
    System.out.print(String.format("%.1f", mid) + " ");
System.out.print(min);
}
}

试题编号: 201909-1_小明种苹果

时间限制: 2.0s
内存限制: 512.0MB
[题目描述]

  小明在他的果园里种了一-些苹果树。为了保证苹果的品质,在种植过程中要进行若干轮疏果操作,也就是提前从树上把不好的苹果去掉。第- ~轮疏果操作开始前,小明记录了每棵树上苹果的个数。每轮疏果操作时,小明都记录了从每棵树上去掉的苹果个数。在最后一轮疏果操作结束后,请帮助小明统计相关的信息。
[输入格式]
从标准输入读入数据。
  第1行包含两个正整数N和M,分别表示苹果树的棵数和疏果操作的轮数。
  第1+i行(1≤i≤N),每行包含M+ 1个整数a[i][0],a[i][1]...a[i][M];
其中a[i][0]为正整数,表示第1轮疏果操作开始前第i棵树上苹果的个数。a[i][j] (1≤j≤M)为零或负整数,表示第j轮疏果操作时从第i棵树上去掉的苹果个数。如果为零,表示没有去掉苹果;如果为负,其绝对值为去掉的苹果个数。
每行中相邻两个数之间用一个空格分隔。
[输出格式]
输出到标准输出。
输出只有一行,包含三个整数T、k和P。其中,

  • T为最后一轮疏果操作后所有苹果树上剩下的苹果总数(假设苹果不会因为其他原因减少);

  • k为疏果个数(也就是疏果操作去掉的苹果个数)最多的苹果树编号(如有并列,
    输出满足条件的最小编号);

  • P为该苹果树的疏果个数。
    相邻两个数之间用一个空格分隔。输入数据保证是正确的,也就是说,每棵树在全部疏果操作结束后剩下的苹果个数是非负的。

[样例1输入]
3 3
73 -8 -6 -4
76 -5 -10 -8
80- 6 -15 0
[样例1输出]
167 2 23
[样例1解释]
  第1棵苹果树的疏果个数为8+6+4=18,第2棵为5+10+8=23,第3棵为6+ 15+0= 21,因此最后一轮疏果操作后全部苹果树上的苹果个数总和为(73- 18)+(76-23)+ (80-21)= 167, 疏果个数最多的是第2棵数,其疏果个数为23.
[样例2输入]
2 2
10 -3 -1
15 -4 0
[样例2输出]
17 1 4
[样例2解释]
两棵树的疏果个数均为4,应该输出编号最小的第1棵树。
[子任务]
图片说明

import java.util.Scanner;

public class 小明种苹果 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(); // 果树行数
int m = sc.nextInt(); // 疏果次数
int sum = 0;// 苹果总数
int max = 0;// dp数组最大元素索引
int apple[][] = new int[n][m + 1]; // m次疏果,第一个数据为原始果子数,一共m+1个数
int dp[] = new int[n + 1];
dp[0] = 0;
for (int i = 0; i < n; i++) {
    for (int j = 0; j < m + 1; j++) {
    apple[i][j] = sc.nextInt();
    sum += apple[i][j];
    }
}
    /*根据题意,只需要把每一行所有数据加起来,就是最终苹果数量。而每一行疏果个数可以用一个数组来纪录,然后找出该数组中最大的元素的索引即可。疏果个数就是该索引在数组中对应的元素。*/
for (int i = 0; i < n; i++) {
    for (int j = 1; j < m + 1; j++) {
    dp[i + 1] += apple[i][j];
    }
}
for (int i = 1; i < n + 1; i++) {
    if (Math.abs(dp[i]) > Math.abs(dp[max]))
    max = i;
}
System.out.println(sum + " " + max + " " + Math.abs(dp[max]));
}
}