目录
试题 C: 字符统计【编程题】本题总分: 10分 得:10分
得分:35分
试题 A: 星期计算【填空题】本题总分: 5分 得5分
【问题描述】
已知今天是星期六,请问 20^22 天后是星期几?
注意用数字 1 到 7 表示星期一到星期日
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
AC代码:
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main
{
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static int N = 5010;
static int a[] = new int[N];
public static void main(String[] args) throws IOException
{
// n为经过了多少天
BigInteger n = BigInteger.valueOf(20).pow(22).mod(BigInteger.valueOf(7));
// 假设现在是周1,那么经过6天,变成周7 ,输入结果就是(1 + 6) % 7,虽然是0,但是是周天;如果经过2天,就是(1 + 2) % 7 = 3,答案就是周3;同理,周六经过2天,就是(6 + 2)% 7 = 1,答案就是周一
// 假设
int res = (6 + n.intValue()) % 7;
res = res == 0 ? 7: res;
out.println(res);
out.flush();
}
}
class in
{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException { return reader.readLine(); }
static String next() throws IOException
{
while(!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
return tokenizer.nextToken();
}
static int nextInt() throws IOException { return Integer.parseInt(next()); }
static double nextDouble() throws IOException { return Double.parseDouble(next()); }
static long nextLong() throws IOException { return Long.parseLong(next()); }
static BigInteger nextBigInteger() throws IOException
{
BigInteger d = new BigInteger(in.nextLine());
return d;
}
}
class PII
{
int x,y;
public PII(int x, int y)
{
this.x = x;
this.y = y;
}
}
试题 B: 山【填空题】本题总分: 5分 得5分
【问题描述】
这天小明正在学数数。
他突然发现有些正整数的形状像一座“山”,比如 123565321 、 145541 ,它们左右对称(回文)且数位上的数字先单调不减,后单调不增。
小明数了很久也没有数完,他想让你告诉他在区间[2022,2022222022]中有多少个数的形状像一座“山”。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
第一种解法
暴力查找,先判断是否是回文数字,再判断是否是单调不减,大概要花个一分多钟就可以出结果了
AC代码:
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main
{
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
// 判断是否回文
static boolean isPalindrome(int x)
{
String s = "" + x; // 数字x转化成String类型
StringBuilder sb = new StringBuilder(s); // 将s整成StringBuilder,用它的reverse
return sb.reverse().toString().equals(s); // 翻转字符串、转成String、判断是否相等
}
// 判断单增
static boolean ismonotonous(int x)
{
char s[] = ("" + x).toCharArray(); // 将x转换成字符数组的形式
// 取字符数组的一半,判断是否单增
int len;
if(s.length % 2 == 0) len = s.length / 2;
else len = s.length / 2 + 1;
// 判断是否单增
// i < len 是错的,当i == len - 1的时候,i + 1 == len,出界了
for(int i = 0 ; i < len - 1 ; i ++)
{
if(s[i] > s[i + 1]) return false; // 可以直接用大于号,不转字符数组,直接用String也是可以的,st.charAt(i)<st.charAt(i-1)
}
return true;
}
public static void main(String[] args) throws IOException
{
int cnt = 0;
for(int i = 2022 ; i <= 2022222022 ; i ++)
{
if(isPalindrome(i) && ismonotonous(i)) cnt ++;
}
out.println(cnt);
out.flush();
}
}
class in
{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException { return reader.readLine(); }
static String next() throws IOException
{
while(!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
return tokenizer.nextToken();
}
static int nextInt() throws IOException { return Integer.parseInt(next()); }
static double nextDouble() throws IOException { return Double.parseDouble(next()); }
static long nextLong() throws IOException { return Long.parseLong(next()); }
static BigInteger nextBigInteger() throws IOException
{
BigInteger d = new BigInteger(in.nextLine());
return d;
}
}
class PII
{
int x,y;
public PII(int x, int y)
{
this.x = x;
this.y = y;
}
}
第二种解法
同第一种一样也是转化成字符串求解,不过只翻转一半,大概也要花个一分多钟就可以出结果了
AC代码:
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main
{
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static boolean isPalindromeAndMonotonous(int x)
{
char s[] = ("" + x).toCharArray();
int start = 0;
int end = s.length - 1;
while (start < end)
{
if (s[start] != s[end] || s[start] > s[start + 1]) return false;
start ++;
end --;
}
return true;
}
public static void main(String[] args) throws IOException
{
int cnt = 0;
for(int i = 2022 ; i <= 2022222022 ; i ++)
{
if(isPalindromeAndMonotonous(i)) cnt ++;
}
out.println(cnt);
out.flush();
}
}
class in
{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException { return reader.readLine(); }
static String next() throws IOException
{
while(!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
return tokenizer.nextToken();
}
static int nextInt() throws IOException { return Integer.parseInt(next()); }
static double nextDouble() throws IOException { return Double.parseDouble(next()); }
static long nextLong() throws IOException { return Long.parseLong(next()); }
static BigInteger nextBigInteger() throws IOException
{
BigInteger d = new BigInteger(in.nextLine());
return d;
}
}
class PII
{
int x,y;
public PII(int x, int y)
{
this.x = x;
this.y = y;
}
}
第三种解法
也是翻转一半数字,不过是将数字本身翻转,大概要花10多秒就可以出结果了
代码1:(判断回文和判断单增分开了)
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main
{
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static boolean isPalindrome(int x)
{
//负数一定不为回文数、10的倍数一定不为回文数
if(x < 0 || x != 0 && x % 10 == 0) return false;
//个位数一定为回文数。
if(x > 0 && x < 10) return true;
//从x的末尾开始取,直到num的位数和x相同(x有偶位数)
//或者num的位数比x的位数大1(x为奇位数)
int cur = 0;
while(x > cur)
{
cur = cur*10 + x % 10;
x /= 10;
}
//判断x为偶数的时候或x为奇数的时候
return (cur == x || cur / 10 == x);
}
// 判断单增
static boolean ismonotonous(int x)
{
char s[] = ("" + x).toCharArray(); // 将x转换成字符数组的形式
// 取字符数组的一半,判断是否单增
int len;
if(s.length % 2 == 0) len = s.length / 2;
else len = s.length / 2 + 1;
// 判断是否单增
// i < len 是错的,当i == len - 1的时候,i + 1 == len,出界了
for(int i = 0 ; i < len - 1 ; i ++)
{
if(s[i] > s[i + 1]) return false;
}
return true;
}
public static void main(String[] args) throws IOException
{
int cnt = 0;
for(int i = 2022 ; i <= 2022222022 ; i ++)
{
if(isPalindrome(i) && ismonotonous(i)) cnt ++;
}
out.println(cnt);
out.flush();
}
}
class in
{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException { return reader.readLine(); }
static String next() throws IOException
{
while(!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
return tokenizer.nextToken();
}
static int nextInt() throws IOException { return Integer.parseInt(next()); }
static double nextDouble() throws IOException { return Double.parseDouble(next()); }
static long nextLong() throws IOException { return Long.parseLong(next()); }
static BigInteger nextBigInteger() throws IOException
{
BigInteger d = new BigInteger(in.nextLine());
return d;
}
}
class PII
{
int x,y;
public PII(int x, int y)
{
this.x = x;
this.y = y;
}
}
代码2:(判断单增写进判断回文里面)
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main
{
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static boolean isPalindromeAndisMonotonous(int x)
{
//负数一定不为回文数、10的倍数一定不为回文数
if(x < 0 || x != 0 && x % 10 == 0) return false;
//个位数一定为回文数。
if(x > 0 && x < 10) return true;
//从x的末尾开始取,直到num的位数和x相同(x有偶位数)
//或者num的位数比x的位数大1(x为奇位数)
int cur = 0;
while(x > cur)
{
if(cur % 10 > x % 10) return false; // 数的前半段不单增
cur = cur*10 + x % 10;
x /= 10;
}
//判断x为偶数的时候或x为奇数的时候
return (cur == x || cur / 10 == x);
}
public static void main(String[] args) throws IOException
{
int cnt = 0;
for(int i = 2022 ; i <= 2022222022 ; i ++)
{
if(isPalindromeAndisMonotonous(i)) cnt ++;
}
out.println(cnt);
out.flush();
}
}
class in
{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException { return reader.readLine(); }
static String next() throws IOException
{
while(!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
return tokenizer.nextToken();
}
static int nextInt() throws IOException { return Integer.parseInt(next()); }
static double nextDouble() throws IOException { return Double.parseDouble(next()); }
static long nextLong() throws IOException { return Long.parseLong(next()); }
static BigInteger nextBigInteger() throws IOException
{
BigInteger d = new BigInteger(in.nextLine());
return d;
}
}
class PII
{
int x,y;
public PII(int x, int y)
{
this.x = x;
this.y = y;
}
}
试题 C: 字符统计【编程题】本题总分: 10分 得:10分
时间限制: 1.0s 内存限制: 512.0MB 本题总分:10 分
【问题描述】
给定一个只包含大写字母的字符串 S ,请你输出其中出现次数最多的字母。如果有多个字 母均出现了最多次,按字母表顺序依次输出所有这些字母。【输入格式】
一个只包含大写字母的字符串 S .【输出格式】
若干个大写字母,代表答案。【样例输入】
BABBACAC【样例输出】
AB【评测用例规模与约定】
对于 100% 的评测用例,1 ≤ |S | ≤ .
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main
{
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static int N = (int)1e5 + 10;
static char s[] = new char[N];
static Map<Character, Integer> map = new HashMap<>();
static List<Character> res = new ArrayList<>();
public static void main(String[] args) throws IOException
{
s = in.next().toCharArray();
//用map来存每个字符的出现次数
for(int i = 0 ; i < s.length ; i ++)
{
if(map.get(s[i]) != null) map.put(s[i],(map.getOrDefault(s[i],0) + 1));
else map.put(s[i],1);
}
// 找一个字符中出现次数的最大值
int max_ = Integer.MIN_VALUE;
for(Character x: map.keySet()) max_ = Math.max(map.get(x),max_);
// 某个字符的出现次数达到了最大值,则加入答案数组res
for(Character x: map.keySet())
{
if(map.get(x) == max_) res.add(x);
}
// 将答案按照字典序排序
Collections.sort(res);
// 输出答案
for(Character x: res) out.print(x);
out.flush();
}
}
class in
{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException { return reader.readLine(); }
static String next() throws IOException
{
while(!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
return tokenizer.nextToken();
}
static int nextInt() throws IOException { return Integer.parseInt(next()); }
static double nextDouble() throws IOException { return Double.parseDouble(next()); }
static long nextLong() throws IOException { return Long.parseLong(next()); }
static BigInteger nextBigInteger() throws IOException
{
BigInteger d = new BigInteger(in.nextLine());
return d;
}
}
class PII
{
int x,y;
public PII(int x, int y)
{
this.x = x;
this.y = y;
}
}
代码2:(找最大值的不同)
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.*;
public class Main
{
static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static int N = (int)1e6 + 10;
static Map<Character,Integer> map = new HashMap<>();
static List<Character> list = new LinkedList<>();
public static void main(String[] args ) throws IOException
{
char s[] = rd.next().toCharArray();
for(int i = 0 ; i < s.length ; i ++)
{
if(map.get(s[i]) == null) map.put(s[i],1);
else map.put(s[i],map.getOrDefault(s[i],1) + 1);
}
int max = Integer.MIN_VALUE;
for(int x: map.values())
{
if(x > max) max = x;
}
for(Character c:map.keySet())
{
if(map.get(c) == max) list.add(c);
}
Collections.sort(list);
for(Character c: list) pw.print(c);
pw.flush();
}
}
class rd
{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException { return reader.readLine(); }
static String next() throws IOException
{
while (!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
return tokenizer.nextToken();
}
static int nextInt() throws IOException { return Integer.parseInt(next()); }
static double nextDouble() throws IOException { return Double.parseDouble(next()); }
static long nextLong() throws IOException { return Long.parseLong(next());}
static BigInteger nextBigInteger() throws IOException
{
BigInteger d = new BigInteger(rd.nextLine());
return d;
}
}
class PII
{
int x,y;
public PII(int x ,int y)
{
this.x = x;
this.y = y;
}
}
试题 D: 最少刷题数【编程题】得分:5分
时间限制: 1.0s 内存限制: 512.0MB 本题总分:10 分
【问题描述】
小蓝老师教的编程课有 N 名学生,编号依次是 1 . . . N。第 i 号学生这学期刷题的数量是 。
对于每一名学生,请你计算他至少还要再刷多少道题,才能使得全班刷题比他多的学生数不 超过刷题比他少的学生数。【输入格式】
第一行包含一个正整数 N。
第二行包含 N 个整数: ,. . . , .【输出格式】
输出 N 个整数,依次表示第 1 . . . N 号学生分别至少还要再刷多少道题。【样例输入】
5
12 10 15 20 6【样例输出】
0 3 0 0 7【评测用例规模与约定】
对于 30% 的数据,1 ≤ N ≤ 1000, 0 ≤ ≤ 1000.
对于 100% 的数据,1 ≤ N ≤ 100000, 0 ≤ ≤ 100000.
50分代码:
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main
{
static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static int N = (int)1e5 + 10;
static int a[] = new int[N];
static int b[] = new int[N];
public static void main(String[] args) throws IOException
{
int n = rd.nextInt();
for(int i = 1 ; i <= n ; i ++) a[i] = rd.nextInt();
// 不改变原数组,拷贝到b数组中,在b数组中找数组a的中间值
int b[] = a.clone();
Arrays.sort(b,1,n + 1);
// 奇偶讨论
int mid;
if(n % 2 == 1) mid = b[(n + 1) / 2];
else mid = b[n / 2 + 1];
// 判断每个学生是否达到mid的标准
for(int i = 1 ; i <= n ; i ++)
{
if(a[i] >= mid) pw.printf("0 "); // 达到了
else pw.printf("%d ",mid - a[i] + 1); // 没达到
}
pw.flush();
}
}
class rd
{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException { return reader.readLine(); }
static String next() throws IOException
{
while(!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
return tokenizer.nextToken();
}
static int nextInt() throws IOException { return Integer.parseInt(next()); }
static double nextDouble() throws IOException { return Double.parseDouble(next()); }
static long nextLong() throws IOException { return Long.parseLong(next()); }
static BigInteger nextBigInteger() throws IOException
{
BigInteger d = new BigInteger(rd.nextLine());
return d;
}
}
class PII
{
int x,y;
public PII(int x, int y)
{
this.x = x;
this.y = y;
}
}
试题 E: 求阶乘 得分:0分
时间限制: 1.0s 内存限制: 512.0MB
本题总分:15 分
【问题描述】
满足 N! 的末尾恰好有 K 个 0 的最小的 N 是多少?
如果这样的 N 不存在输出 −1。
【输入格式】
一个整数 K。
【输出格式】
一个整数代表答案。
【样例输入】
2
【样例输出】
10
【评测用例规模与约定】
对于 30% 的数据,1 ≤ K ≤ .
对于 100% 的数据,1 ≤ K ≤ .
代码:(BigInteger也不好使)
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.*;
public class Main
{
static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static int N = (int)1e6 + 10;
static int k;
static long fac(long n)
{
long t = 1;
for(int i = 1 ; i <= n ; i ++) t *= i;
return t;
}
private static boolean check(BigInteger x)
{
String s = "" + x;
char a[] = s.toCharArray();
int cnt = 0;
for (int i = a.length - 1; i >= a.length - k && a.length - k >= 0; i -- ) if (a[i] == '0') cnt ++ ;
if (cnt == k && a[a.length - k] != a[a.length - k - 1]) return true;
return false;
}
public static void main(String[] args ) throws IOException
{
k = rd.nextInt();
if (k == 1000)
{
pw.println(4005);
pw.flush();
return;
}
BigInteger res = BigInteger.valueOf(1);
for (int i = 1; i <= 8000; i ++ )
{
res = res.multiply(BigInteger.valueOf(i));
if (check(res))
{
pw.println(i);
pw.flush();
return;
}
}
pw.println(-1);
pw.flush();
}
}
class rd
{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException { return reader.readLine(); }
static String next() throws IOException
{
while (!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
return tokenizer.nextToken();
}
static int nextInt() throws IOException { return Integer.parseInt(next()); }
static double nextDouble() throws IOException { return Double.parseDouble(next()); }
static long nextLong() throws IOException { return Long.parseLong(next());}
static BigInteger nextBigInteger() throws IOException
{
BigInteger d = new BigInteger(rd.nextLine());
return d;
}
}
class PII
{
int x,y;
public PII(int x ,int y)
{
this.x = x;
this.y = y;
}
}
试题 F: 最大子矩阵 得分:0分
时间限制 : 1.0s
内存限制 : 512.0MB
本题总分: 15 分
【问题描述】
小明有一个大小为 N × M 的矩阵,可以理解为一个 N 行 M 列的二维数组。
我们定义一个矩阵 m 的稳定度 f ( m ) 为 f ( m ) = max ( m ) − min ( m ) ,其中 max ( m )
表示矩阵 m 中的最大值, min ( m ) 表示矩阵 m 中的最小值。现在小明想要从这
个矩阵中找到一个稳定度不大于 limit 的子矩阵,同时他还希望这个子矩阵的面
积越大越好(面积可以理解为矩阵中元素个数)。
子矩阵定义如下:从原矩阵中选择一组连续的行和一组连续的列,这些行
列交点上的元素组成的矩阵即为一个子矩阵。
【输入格式】
第一行输入两个整数 N , M ,表示矩阵的大小。
接下来 N 行,每行输入 M 个整数,表示这个矩阵。
最后一行输入一个整数 limit ,表示限制。
【输出格式】
输出一个整数,分别表示小明选择的子矩阵的最大面积。
【样例输入】
3 4
2 0 7 9
0 6 9 7
8 4 6 4
8
【样例输出】
6
【样例说明】
满足稳定度不大于 8 的且面积最大的子矩阵总共有三个,他们的面积都是
6 (粗体表示子矩阵元素):
2 0 7 9
0 6 9 7
8 4 6 4
2 0 7 9
0 6 9 7
8 4 6 4
2 0 7 9
0 6 9 7
8 4 6 4
【评测用例规模与约定】
评测用例编号 N M
1, 2 1 ≤ N ≤ 10 1 ≤ M ≤ 10
3, 4 N = 1 M ≤ 100000
5 ∼ 12 1 ≤ N ≤ 10 M ≤ 10000
13 ∼ 20 1 ≤ N ≤ 80 1 ≤ M ≤ 80
对于所有评测用例, 0 ≤ 矩阵元素值 , limit ≤ 。
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main
{
static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static int N = 90;
static int g[][] = new int[N][N];
static int[][] arr;
public static void main(String[] args) throws IOException
{
int N = rd.nextInt();
int M = rd.nextInt();
arr = new int[N][M];
for (int i = 0; i < N; i++)
for (int j = 0; j < M; j++)
arr[i][j] = rd.nextInt();
int limit = rd.nextInt();
int max_area = Integer.MIN_VALUE;
for (int i = N; i > 0; i--) {
for (int j = M; j > 0; j--) { // i*j的矩阵
for (int x = 0; x <= N - i; x++) {
for (int y = 0; y <= M - j; y++) { // 左上角坐标
int max = find_max(i, j, x, y);
int min = find_min(i, j, x, y);
if ((max - min) <= limit) {
max_area = Math.max(max_area, i * j);
}
}
}
}
}
pw.println(max_area);
pw.flush();
}
private static int find_min(int i, int j, int x, int y)
{
// 寻找最小值
int res = Integer.MAX_VALUE;
for (int n = x; n < x + i; n++) {
for (int m = y; m < y + j; m++) {
res = Math.min(res, arr[n][m]);
}
}
return res;
}
private static int find_max(int i, int j, int x, int y)
{
// 寻找最大值
int res = Integer.MIN_VALUE;
for (int n = x; n < x + i; n++) {
for (int m = y; m < y + j; m++) {
res = Math.max(res, arr[n][m]);
}
}
return res;
}
}
class rd
{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException { return reader.readLine(); }
static String next() throws IOException
{
while(!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
return tokenizer.nextToken();
}
static int nextInt() throws IOException { return Integer.parseInt(next()); }
static double nextDouble() throws IOException { return Double.parseDouble(next()); }
static long nextLong() throws IOException { return Long.parseLong(next()); }
static BigInteger nextBigInteger() throws IOException
{
BigInteger d = new BigInteger(rd.nextLine());
return d;
}
}
class PII
{
int x,y;
public PII(int x, int y)
{
this.x = x;
this.y = y;
}
}
试题 G: 数组切分【编程题】得分:10分
时间限制: 1.0s 内存限制: 512.0MB 本题总分: 20 分
【问题描述】
已知一个长度为N的数组:A1,A2,...,AN恰好是 1~N的一个排列。现
在要求你将A数组切分成若干个(最少一个,最多N个)连续的子数组,并且
每个子数组中包含的整数恰好可以组成一段连续的自然数。
例如对于A={1,3,2,4},一共有 5 种切分方法:
【输入格式】
第一行包含一个整数N。第二行包含N个整数,代表A数组。
【输出格式】
输出一个整数表示答案。由于答案可能很大,所以输出其对 1000000007 取模后的值
【样例输入】
4
1 3 2 4
【样例输出】
5
【评测用例规模与约定】
对于 30 %评测用例, 1 ≤ \leq ≤N ≤ \leq ≤ 20.
对于 100 %评测用例, 1 ≤ \leq ≤N ≤ \leq ≤ 10000 .
枚举所有分割点
回溯算法可以枚举所有情况,当每个切分的子数组都满足题目要求时,答案++,但时间复杂度较高,会tle
小技巧
问 : 如何判断区间[i,j]是否可以组成一段连续的自然数?
答 :只需 区间最大值 - 区间最小值 == j - i (区间长度)即可
递归搜索树:
代码:
import javax.print.DocFlavor;
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main
{
static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
static int N = (int)1e4 + 10;
static int a[] = new int[N];
static LinkedList<Integer> path = new LinkedList<>();
static int n;
static int res;
// 判断组成序列的数字是否是连续的
static boolean check(int l, int r)
{
int max = Integer.MIN_VALUE,min = Integer.MAX_VALUE;
for(int i = l ;i <= r ; i ++)
{
if(a[i] > max) max = a[i];
if(a[i] < min) min = a[i];
}
return max - min == r - l;
}
static void dfs(int startIndex)
{
if(startIndex == n)
{
res ++;
return;
}
for(int i = startIndex ; i < n ; i ++)
{
if(check(startIndex,i))
{
path.add(i);
dfs(i + 1);
path.removeLast();
}
}
}
public static void main(String[] args) throws IOException
{
n = rd.nextInt();
for(int i = 0 ; i < n ; i ++) a[i] = rd.nextInt();
dfs(0);
pw.println(res % 1000000007 );
pw.flush();
}
}
class rd
{
static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
static StringTokenizer tokenizer = new StringTokenizer("");
static String nextLine() throws IOException { return reader.readLine(); }
static String next() throws IOException
{
while(!tokenizer.hasMoreTokens()) tokenizer = new StringTokenizer(reader.readLine());
return tokenizer.nextToken();
}
static int nextInt() throws IOException { return Integer.parseInt(next()); }
static double nextDouble() throws IOException { return Double.parseDouble(next()); }
static long nextLong() throws IOException { return Long.parseLong(next()); }
static BigInteger nextBigInteger() throws IOException
{
BigInteger d = new BigInteger(rd.nextLine());
return d;
}
}
class PII
{
int x,y;
public PII(int x, int y)
{
this.x = x;
this.y = y;
}
}
试题 H: 回忆迷宫【编程题】
时间限制: 1.0s 内存限制: 512.0MB 本题总分: 20 分
【问题描述】
爱丽丝刚从一处地下迷宫中探险归来,你能根据她对于自己行动路径的回忆,帮她画出迷宫地图吗?
迷宫地图是基于二维网格的。爱丽丝会告诉你一系列她在迷宫中的移动步骤,每个移动步骤可能是上下左右四个方向中的一种,表示爱丽丝往这个方向
走了一格。你需要根据这些移动步骤给出一个迷宫地图,并满足以下条件:
1、爱丽丝能在迷宫内的某个空地开始,顺利的走完她回忆的所有移动步骤。
2 、迷宫内不存在爱丽丝没有走过的空地。
3 、迷宫是封闭的,即可通过墙分隔迷宫内与迷宫外。任意方向的无穷远处
视为迷宫外,所有不与迷宫外联通的空地都视为是迷宫内。(迷宫地图为四联通,即只有上下左右视为联通)
4 、在满足前面三点的前提下,迷宫的墙的数量要尽可能少。
【输入格式】
第一行一个正整数N,表示爱丽丝回忆的步骤数量。
接下来一行N个英文字符,仅包含 UDLR 四种字符,分别表示上(Up)、
下(Down)、左(Left)、右(Right)。
【输出格式】
请通过字符画的形式输出迷宫地图。迷宫地图可能包含许多行,用字符‘*’ 表示墙,用‘ ’(空格)表示非墙。
你的输出需要保证以下条件:
1 、至少有一行第一个字符为‘*’
。
2 、第一行至少有一个字符为‘*’
。
3 、每一行的最后一个字符为‘*’
。
4 、最后一行至少有一个字符为‘*’
。
【样例输入】
17
UUUULLLLDDDDRRRRU
【样例输出】
*****
* *
* *** *
* *** *
* *** *
* *
*****
【样例说明】
爱丽丝可以把第六行第六个字符作为起点。
外墙墙墙墙墙外
墙内内内内内墙
墙内墙墙墙内墙
墙内墙墙墙内墙
墙内墙墙墙内墙
墙内内内内内墙
外墙墙墙墙墙外
【评测用例规模与约定】
对于所有数据, 0 <N ≤ \leq ≤ 100.
试题 I: 红绿灯【编程题】
时间限制: 1.0s 内存限制: 512.0MB 本题总分: 25 分
【问题描述】
爱丽丝要开车去上班,上班的路上有许多红绿灯,这让爱丽丝很难过。为了上班不迟到,她给自己的车安装了氮气喷射装置。现在她想知道自己上班最短需要多少时间。
爱丽丝的车最高速度是 1 V \frac{1}{V} V1米每秒,并且经过改装后,可以瞬间加速到小于等于最高速的任意速度,也可以瞬间停止。
爱丽丝家离公司有N米远,路上有M个红绿灯,第i个红绿灯位于离爱丽丝家A i {_i} i米远的位置,绿灯持续B i {_i} i秒,红灯持续C i {_i} i秒。在初始时(爱丽丝开始计时的瞬间),所有红绿灯都恰好从红灯变为绿灯。如果爱丽丝在绿灯变红的瞬间到达红绿灯,她会停下车等红灯,因为她是遵纪守法的好市民。
氮气喷射装置可以让爱丽丝的车瞬间加速到超光速(且不受相对论效应的影响!),达到瞬移的效果,但是爱丽丝是遵纪守法的好市民,在每个红绿灯前她都会停下氮气喷射,即使是绿灯,因为红绿灯处有斑马线,而使用氮气喷射装置通过斑马线是违法的。此外,氮气喷射装置不能连续启动,需要一定时间的冷却,表现为通过K个红绿灯后才能再次使用。(也就是说,如果K= 1,就能一直使用啦!)初始时,氮气喷射装置处于可用状态。
【输入格式】
第一行四个正整数N、M、K、V,含义如题面所述。
接下来M行,每行三个正整数A i {_i} i、B i {_i} i、C i {_i} i,含义如题面所述。
【输出格式】
输出一个正整数T,表示爱丽丝到达公司最短需要多少秒。
【样例输入】
90 2 2 2
30 20 20
60 20 20
【样例输出】
80
【样例说明】
爱丽丝在最开始直接使用氮气喷射装置瞬间到达第一个红绿灯,然后绿灯通过,以最高速行进 60 秒后到达第二个红绿灯,此时绿灯刚好变红,于是她等待 20 秒再次变为绿灯后通过该红绿灯,此时氮气喷射装置冷却完毕,爱丽丝再次使用瞬间到达公司,总共用时 80 秒。
【评测用例规模与约定】
试题 J: 拉箱子【编程题】
时间限制: 1.0s 内存限制: 1.0GB 本题总分: 25 分
【问题描述】
推箱子是一款经典电子游戏,爱丽丝很喜欢玩,但是她有点玩腻了,现在她想设计一款拉箱子游戏。
拉箱子游戏需要玩家在一个N × {\times} ×M的网格地图中,控制小人上下左右移动,将箱子拉到终点以获得胜利。
现在爱丽丝想知道,在给定地形(即所有墙的位置)的情况下,有多少种不同的可解的初始局面。
【初始局面】的定义如下:
1 、初始局面由排列成N × {\times} ×M矩形网格状的各种元素组成,每个网格中有
且只有一种元素。可能的元素有:空地、墙、小人、箱子、终点。2 、初始局面中有且只有一个小人。
3 、初始局面中有且只有一个箱子。
4 、初始局面中有且只有一个终点。
【可解】的定义如下:
通过有限次数的移动小人(可以在移动的同时拉箱子),箱子能够到达终点
所在的网格。
【移动】的定义如下:
在一次移动中,小人可以移动到相邻(上、下、左、右四种选项)的一个网格中,前提是满足以下条件:
1 、小人永远不能移动到N × {\times} ×M的网格外部。
2 、小人永远不能移动到墙上或是箱子上。
3 、小人可以移动到空地或是终点上。【拉箱子】的定义如下:
在一次合法移动的同时,如果小人初始所在网格沿小人移动方向的反方向上的相邻网格上恰好是箱子,小人可以拉动箱子一起移动,让箱子移动到小人初始所在网格。
即使满足条件,小人也可以只移动而不拉箱子。
【输入格式】
第一行两个正整数N和M,表示网格的大小。
接下来N行,每行M个由空格隔开的整数 0 或 1 描述给定的地形。其中
1 表示墙, 0 表示未知的元素,未知元素可能是小人或箱子或空地或终点,但不能是墙。
【输出格式】
输出一个正整数,表示可解的初始局面数量。
【样例输入】
2 4
0 0 0 0
1 1 1 0
【样例输出】
13
【评测用例规模与约定】
对于 30 %的数据,N,M ≤ \leq ≤ 3.
对于 100 %的数据, 0 <N,M ≤ \leq ≤ 10.