P1042 [NOIP2003 普及组] 乒乓球
解题步骤(看注释)
读取输入:
- 使用
Scanner
读取所有输入,直到遇到字符E
。- 将输入中的所有字符(除去
E
)拼接成一个字符串。处理比赛结果:
- 分别按照11分制和21分制处理输入字符串,计算每局的结果。
- 将每局的结果存储在
List
中,以便后续输出。输出结果:
- 按顺序输出11分制和21分制的比赛结果。
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
StringBuilder inputBuilder = new StringBuilder();
// 读取输入,直到输入包含“E”
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.contains("E")) {
// 截取输入中“E”之前的字符串
inputBuilder.append(line, 0, line.indexOf('E'));
break;
}
inputBuilder.append(line);
}
String input = inputBuilder.toString();
// 处理游戏,游戏分数为11
List<String> results11 = processGames(input, 11);
// 处理游戏,游戏分数为21
List<String> results21 = processGames(input, 21);
// 输出结果,游戏分数为11
for (String result : results11) {
System.out.println(result);
}
System.out.println();
// 输出结果,游戏分数为21
for (String result : results21) {
System.out.println(result);
}
scanner.close();
}
private static List<String> processGames(String input, int gamePoint) {
List<String> results = new ArrayList<>();
int playerA = 0, playerB = 0;
// 遍历输入中的每个字符
for (char point : input.toCharArray()) {
if (point == 'W') {
// A得分
playerA++;
} else if (point == 'L') {
// B得分
playerB++;
}
// 当A或B的分数大于或等于gamePoint,且两者的分数差大于等于2时,记录结果
if ((playerA >= gamePoint || playerB >= gamePoint) && Math.abs(playerA - playerB) >= 2) {
results.add(playerA + ":" + playerB);
playerA = 0;
playerB = 0;
}
}
// 记录最终结果
results.add(playerA + ":" + playerB);
return results;
}
}
P2670 [NOIP2015 普及组] 扫雷游戏
解题步骤
读取输入:首先,我们需要读取网格的尺寸(
n
和m
),然后读取网格本身,其中包含用于地雷的字符'*'
和'?'
。初始化结果网格:创建一个网格来存储结果,该结果将是输入网格的副本。这最终将包含代表每个非地雷单元的相邻地雷计数的数字。
定义方向:定义要检查每个单元格周围的八个可能的方向(上、下、左、右和四个对角线)。
遍历网格:对于网格中的每个单元格:
- 如果它是一个地雷(
'*'
),我们不需要为该单元格做任何事情。- 如果不是地雷 (
'?'
),请计算相邻单元格中的地雷数量。输出结果网格:以与输入相同的格式打印结果网格。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取输入的n和m
int n = scanner.nextInt();
int m = scanner.nextInt();
scanner.nextLine();
// 初始化grid数组
char[][] grid = new char[n][m];
for (int i = 0; i < n; i++) {
grid[i] = scanner.nextLine().toCharArray();
}
// 初始化dx和dy数组
int[] dx = {-1, -1, -1, 0, 0, 1, 1, 1};
int[] dy = {-1, 0, 1, -1, 1, -1, 0, 1};
// 初始化resultGrid数组
char[][] resultGrid = new char[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == '*') {
resultGrid[i][j] = '*';
} else {
// 计算grid[i][j]周围的雷的数量
int mineCount = 0;
for (int d = 0; d < 8; d++) {
int ni = i + dx[d];
int nj = j + dy[d];
if (ni >= 0 && ni < n && nj >= 0 && nj < m && grid[ni][nj] == '*') {
mineCount++;
}
}
resultGrid[i][j] = (char) (mineCount + '0');
}
}
}
// 输出结果
for (int i = 0; i < n; i++) {
System.out.println(resultGrid[i]);
}
scanner.close();
}
}
P1563 [NOIP2016 提高组] 玩具谜题
解题步骤
- 读取输入:读取节点数
n
和指令数m
,然后读取每个节点的信息。- 初始化节点数组:创建一个数组存储每个节点的信息。
- 处理指令:根据每条指令更新当前节点的位置。
- 输出结果:输出最终的当前节点的名称。
import java.util.Scanner;
class Node {
int head;
String name;
Node(int head, String name) {
this.head = head;
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取n和m
int n = scanner.nextInt();
int m = scanner.nextInt();
scanner.nextLine(); // 消耗换行符
// 初始化数组
Node[] a = new Node[n];
// 读取每个节点的信息
for (int i = 0; i < n; i++) {
int head = scanner.nextInt();
String name = scanner.next();
a[i] = new Node(head, name);
}
int now = 0;
// 处理每个操作
for (int i = 1; i <= m; i++) {
int x = scanner.nextInt();
int y = scanner.nextInt();
if (a[now].head == 0 && x == 0) {
now = (now + n - y) % n;
} else if (a[now].head == 0 && x == 1) {
now = (now + y) % n;
} else if (a[now].head == 1 && x == 0) {
now = (now + y) % n;
} else if (a[now].head == 1 && x == 1) {
now = (now + n - y) % n;
}
}
// 输出结果
System.out.println(a[now].name);
scanner.close();
}
}
P1601 A+B Problem(高精)
import java.math.BigInteger;
import java.util.Scanner;
/**
* @Author HeShen.
* @Date 2024/3/16 21:03
*/
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
BigInteger a = new BigInteger(input.next());
BigInteger b = new BigInteger(input.next());
System.out.println(b.add(a));
}
}
P1303 A*B Problem
import java.math.BigInteger;
import java.util.Scanner;
/**
* @Author HeShen.
* @Date 2024/3/16 21:03
*/
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
BigInteger a = new BigInteger(input.next());
BigInteger b = new BigInteger(input.next());
System.out.println(b.multiply(a));
}
}
P1009 [NOIP1998 普及组] 阶乘之和
import java.util.*;
import java.math.*;
public class Main {
static BigInteger jc(int n) {
BigInteger i=new BigInteger("1");
for (int j=2;j<=n;j++) i=i.multiply(new BigInteger(Integer.toString(j)));
return i;
}
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
int n=scan.nextInt();
scan.close();
BigInteger sum=new BigInteger("0");
for (int i=1;i<=n;i++) sum=sum.add(jc(i));
scan.close();
System.out.println(sum);
}
}
// import java.util.Scanner;
// public class Main {
// public static void main(String[] args) {
// Scanner input = new Scanner(System.in);
// int n = input.nextInt();
// long N = 1;long sum = 0;
// for (int i = 1; i <= n; i++) {
// N *= i;
// sum += N;
// }
// System.out.println(sum);
// }
// }
P4924 [1007] 魔法少女小Scarlet
解题步骤
初始化矩阵:
- 按行优先顺序使用从 1 到 的值填充矩阵。
定义旋转函数:
- 对于给定的中心
(x, y)
和半径r
,提取子矩阵。- 通过重新排列元素来顺时针或逆时针旋转子矩阵。
- 将旋转后的子矩阵复制回原始矩阵。
处理每个旋转命令:
- 根据中心和半径提取每个命令的子矩阵。
- 应用命令指定的旋转。
- 将旋转后的子矩阵放回主矩阵中。
逐行打印矩阵。
按照上述所说解题可能会存在超时现象(洛谷最后一个用例)。可以改进一下:
优化策略
- 减少数据复制: 避免提取和重建子矩阵,直接在原矩阵上操作。
- 旋转逻辑优化: 使用更高效的算法来进行矩阵的旋转操作。
具体优化步骤如下:
直接在原矩阵上进行旋转:
- 通过旋转算法,将以中心
(x, y)
为中心的子矩阵进行旋转。- 使用一个临时数组
temp
存储旋转后的结果,然后再将其写回原矩阵。高效旋转逻辑:
- 通过一次遍历直接进行旋转,减少了重复的操作。
- 针对顺时针和逆时针两种旋转,分别处理。
import java.util.Scanner;
public class MagicGirlScarlet {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
int[][] matrix = new int[n][n];
int value = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
matrix[i][j] = value++;
}
}
for (int k = 0; k < m; k++) {
int x = scanner.nextInt() - 1;
int y = scanner.nextInt() - 1;
int r = scanner.nextInt();
int z = scanner.nextInt();
rotate(matrix, x, y, r, z);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (j > 0) System.out.print(" ");
System.out.print(matrix[i][j]);
}
System.out.println();
}
scanner.close();
}
private static void rotate(int[][] matrix, int x, int y, int r, int z) {
int size = 2 * r + 1;
int[][] temp = new int[size][size];
// 将原始矩阵中需要旋转的部分复制到临时矩阵中
for (int i = 0; i < size; i++) {
System.arraycopy(matrix[x - r + i], y - r, temp[i], 0, size);
}
// 根据旋转方向,将临时矩阵中的元素复制回原始矩阵
if (z == 0) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
matrix[x - r + j][y - r + size - 1 - i] = temp[i][j];
}
}
} else {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
matrix[x - r + size - 1 - j][y - r + i] = temp[i][j];
}
}
}
}
}
P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布
解题步骤
初始化和输入读取:
- 读取比赛轮数
n
,选手 A 的手势序列长度na
和选手 B 的手势序列长度nb
。- 读取选手 A 和选手 B 的手势序列。
定义得分表:
- 根据游戏规则,定义一个二维数组
vs
来表示不同手势之间的胜负关系。进行比赛并计算得分:
- 使用循环处理每一轮比赛,根据选手的手势序列和当前轮次,计算每个选手的得分。
输出结果:
- 打印两个选手的最终得分。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取 n, na, nb
int n = scanner.nextInt();
int na = scanner.nextInt();
int nb = scanner.nextInt();
int[] a = new int[na];
int[] b = new int[nb];
// 读取序列 a
for (int i = 0; i < na; i++) {
a[i] = scanner.nextInt();
}
// 读取序列 b
for (int i = 0; i < nb; i++) {
b[i] = scanner.nextInt();
}
// 得分表
int[][] vs = {
{0, 0, 1, 1, 0},
{1, 0, 0, 1, 0},
{0, 1, 0, 0, 1},
{0, 0, 1, 0, 1},
{1, 1, 0, 0, 0}
};
int cnta = 0, cntb = 0;
// 进行 n 轮比赛
for (int i = 0; i < n; i++) {
cnta += vs[a[i % na]][b[i % nb]];
cntb += vs[b[i % nb]][a[i % na]];
}
// 输出结果
System.out.println(cnta + " " + cntb);
scanner.close();
}
}
P1518 [USACO2.4] 两只塔姆沃斯牛 The Tamworth Two
解题步骤
要解决这个问题,我们需要模拟 Farmer John 和两只牛在 10x10 网格上的移动。每个角色(Farmer John 和牛)有固定的移动规则:
- 如果前方无障碍(包括地图边界),它们会向前移动。
- 如果前方有障碍,它们会顺时针转 90 度。
我们需要使用广度优先搜索(BFS)来模拟它们的移动,并检查它们是否在某一步相遇。
关键点
- 移动和旋转规则:
- 移动规则:检查前方是否有障碍,如果没有就前进,否则顺时针转向。
- 状态表示:
- 每个角色的状态可以用其位置和方向来表示。
- 两个角色的状态组合起来表示整个系统的状态。
- 广度优先搜索(BFS):
- 使用 BFS 来模拟每分钟的移动,直到两个角色相遇或达到最大步数。
实现步骤
- 读取并解析输入地图。
- 初始化 Farmer John 和牛的初始状态(位置和方向)。
- 使用 BFS 来模拟移动:
- 在每一步中,根据当前状态计算下一步可能的状态。
- 如果两个角色在某步末相遇,则返回当前步数。
- 如果所有可能状态都遍历完仍未相遇,则返回 0。
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
//EMPTY未使用,可以删
private static final int N = 10;
private static final char OBSTACLE = '*';
private static final char EMPTY = '.';
private static final char COWS = 'C';
private static final char FARMER = 'F';
private static final int[] dx = {-1, 0, 1, 0}; // 北, 东, 南, 西
private static final int[] dy = {0, 1, 0, -1};
private static class State {
int fx, fy, fd, cx, cy, cd;
int steps;
State(int fx, int fy, int fd, int cx, int cy, int cd, int steps) {
this.fx = fx;
this.fy = fy;
this.fd = fd;
this.cx = cx;
this.cy = cy;
this.cd = cd;
this.steps = steps;
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
char[][] map = new char[N][N];
int fx = 0, fy = 0, cx = 0, cy = 0;
// 读取地图并找到 Farmer John 和牛的位置
for (int i = 0; i < N; i++) {
map[i] = scanner.next().toCharArray();
for (int j = 0; j < N; j++) {
if (map[i][j] == FARMER) {
fx = i;
fy = j;
} else if (map[i][j] == COWS) {
cx = i;
cy = j;
}
}
}
// 使用 BFS 进行模拟
boolean[][][][][][] visited = new boolean[N][N][4][N][N][4];
Queue<State> queue = new LinkedList<>();
queue.add(new State(fx, fy, 0, cx, cy, 0, 0)); // 初始方向均为北(0)
visited[fx][fy][0][cx][cy][0] = true;
while (!queue.isEmpty()) {
State current = queue.poll();
if (current.fx == current.cx && current.fy == current.cy) {
System.out.println(current.steps);
return;
}
// 计算 Farmer John 的下一个状态
int nfx = current.fx + dx[current.fd];
int nfy = current.fy + dy[current.fd];
int nfd = current.fd;
if (nfx < 0 || nfx >= N || nfy < 0 || nfy >= N || map[nfx][nfy] == OBSTACLE) {
nfd = (current.fd + 1) % 4; // 顺时针转 90 度
nfx = current.fx;
nfy = current.fy;
}
// 计算牛的下一个状态
int ncx = current.cx + dx[current.cd];
int ncy = current.cy + dy[current.cd];
int ncd = current.cd;
if (ncx < 0 || ncx >= N || ncy < 0 || ncy >= N || map[ncx][ncy] == OBSTACLE) {
ncd = (current.cd + 1) % 4; // 顺时针转 90 度
ncx = current.cx;
ncy = current.cy;
}
if (!visited[nfx][nfy][nfd][ncx][ncy][ncd]) {
visited[nfx][nfy][nfd][ncx][ncy][ncd] = true;
queue.add(new State(nfx, nfy, nfd, ncx, ncy, ncd, current.steps + 1));
}
}
System.out.println(0); // 如果没有相遇,则输出 0
scanner.close();
}
}
P1067 [NOIP2009 普及组] 多项式输出
解题步骤
- 读取输入数据:读取多项式的次数
n
和每项的系数。- 处理每个系数:根据系数的值和项的次数构建多项式字符串,注意处理系数为 0 的情况。
- 格式化输出:
- 最高次项的系数如果是正数,前面不需要加
+
号,如果是负数,则以-
号开头。- 非最高次项根据其系数是正数还是负数,加
+
或-
号。- 系数的绝对值为 1 且指数不为 0 的项,不需要显示系数的
1
。- 处理指数的显示形式(
x^b
,x
,或省略x
)。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取多项式次数
int n = scanner.nextInt();
// 读取各项系数
int[] coefficients = new int[n + 1];
for (int i = 0; i <= n; i++) {
coefficients[i] = scanner.nextInt();
}
StringBuilder polynomial = new StringBuilder();
boolean firstTerm = true;
for (int i = 0; i <= n; i++) {
int coefficient = coefficients[i];
int degree = n - i;
if (coefficient == 0) {
continue; // 跳过系数为0的项
}
// 处理符号
if (firstTerm) {
if (coefficient < 0) {
polynomial.append("-");
}
firstTerm = false;
} else {
if (coefficient > 0) {
polynomial.append("+");
} else {
polynomial.append("-");
}
}
// 处理系数绝对值
if (Math.abs(coefficient) != 1 || degree == 0) {
polynomial.append(Math.abs(coefficient));
}
// 处理指数部分
if (degree > 1) {
polynomial.append("x^").append(degree);
} else if (degree == 1) {
polynomial.append("x");
}
}
System.out.println(polynomial.toString());
scanner.close();
}
}
P1098 [NOIP2007 提高组] 字符串的展开
解题步骤
读取输入和解析参数:
- 读取三个参数
p1
,p2
,p3
。- 读取需要处理的字符串。
处理每一个可能的展开情况:
- 遇到
-
,检查其两侧字符是否满足展开条件(同为小写字母或数字且右侧字符大于左侧字符)。- 如果满足条件,根据
p1
,p2
,p3
进行相应的展开和格式化。构建结果字符串:
- 使用
StringBuilder
来高效地构建字符串。- 处理每个字符,如果遇到可展开的模式,根据规则生成展开部分并添加到结果中。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取参数
int p1 = scanner.nextInt();
int p2 = scanner.nextInt();
int p3 = scanner.nextInt();
scanner.nextLine(); // 吃掉换行符
String input = scanner.nextLine();
StringBuilder result = new StringBuilder();
int i = 0;
while (i < input.length()) {
char current = input.charAt(i);
if (current == '-' && i > 0 && i < input.length() - 1) {
char left = input.charAt(i - 1);
char right = input.charAt(i + 1);
// 检查是否可以展开
if ((Character.isLowerCase(left) && Character.isLowerCase(right) && left < right) ||
(Character.isDigit(left) && Character.isDigit(right) && left < right)) {
// 不直接处理当前的 '-',而是进入展开逻辑
char start = (char) (left + 1);
char end = right;
StringBuilder expanded = new StringBuilder();
for (char ch = start; ch < end; ch++) {
char toAppend = ch;
if (p1 == 2 && Character.isLowerCase(ch)) {
toAppend = Character.toUpperCase(ch);
} else if (p1 == 3) {
toAppend = '*';
}
for (int j = 0; j < p2; j++) {
expanded.append(toAppend);
}
}
if (p3 == 2) { // 如果需要逆序
expanded.reverse();
}
result.append(expanded);
} else {
// 不能展开,直接添加
result.append(current);
}
} else {
// 非 '-' 或者不能展开,直接添加
result.append(current);
}
i++;
}
System.out.println(result.toString());
scanner.close();
}
}
P1065 [NOIP2006 提高组] 作业调度方案
解题步骤
初始化和输入读取:
- 读取机器数量
m
和工件数量n
。- 读取工件加工顺序。
- 读取每个工件的每道工序所使用的机器编号。
- 读取每道工序的加工时间。
模拟加工过程:
- 使用数组记录每台机器的使用情况。
- 对于每道工序,找到机器的空闲时间段并记录加工时间。
- 更新工件的加工完成时间和整体加工时间。
输出结果:
- 输出所有工件完成加工所需的总时间。
import java.util.Scanner;
class Information {
int id; // 在第 id 台机器上加工
int cost; // 花费 cost 时间
Information(int id, int cost) {
this.id = id;
this.cost = cost;
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取 m 和 n
int m = scanner.nextInt();
int n = scanner.nextInt();
// 工件加工顺序列表
int[] list = new int[m * n + 1];
// 读取工件加工顺序
for (int i = 1; i <= m * n; i++) {
list[i] = scanner.nextInt();
}
// 初始化工件加工信息数组
Information[][] a = new Information[n + 1][m + 1];
// 读取每个工件的每道工序所使用的机器号
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
int id = scanner.nextInt();
a[i][j] = new Information(id, 0); // 先设置 id,稍后再设置 cost
}
}
// 读取每个工件的每道工序的加工时间
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
int cost = scanner.nextInt();
a[i][j].cost = cost; // 设置 cost
}
}
// 机器使用情况
int[][] mac = new int[21][100001]; // 初始化时,数组元素默认为 0
// 每个工件加工到第几步
int[] step = new int[21];
// 每个工件上次加工完的时间
int[] las_time = new int[21];
int ans = 0;
// 处理每个操作
for (int i = 1; i <= m * n; i++) {
int now = list[i];
step[now]++;
int id = a[now][step[now]].id;
int cost = a[now][step[now]].cost;
int s = 0;
for (int j = las_time[now] + 1;; j++) {
if (mac[id][j] == 0) {
s++;
} else {
s = 0;
}
if (s == cost) {
for (int k = j - cost + 1; k <= j; k++) {
mac[id][k] = 1;
}
if (j > ans) ans = j;
las_time[now] = j;
break;
}
}
}
// 输出结果
System.out.println(ans);
scanner.close();
}
}
P1786 帮贡排序
解题步骤
- 读取输入:读取所有帮派成员的信息,包括他们的名字、职位、帮贡和等级。
- 初始化职位优先级映射:定义职位的优先级,以便后续排序时使用。
- 分类和排序:按照帮贡对成员进行第一次排序,忽略帮主和副帮主的位置。
- 分配新职位:根据排序后的结果重新分配职位。
- 最终排序和输出:根据新职位和等级对所有成员进行最终排序,并输出结果。
import java.util.*;
class Member {
String name; // 名字
String originalPosition; // 原职位
String newPosition; // 新职位
long contribution; // 帮贡
int level; // 等级
int index; // 输入顺序索引
Member(String name, String originalPosition, long contribution, int level, int index) {
this.name = name;
this.originalPosition = originalPosition;
this.contribution = contribution;
this.level = level;
this.index = index;
}
}
public class Main {
// 映射职位到优先级
static Map<String, Integer> positionMap = new HashMap<>();
static {
positionMap.put("BangZhu", 0);
positionMap.put("FuBangZhu", 1);
positionMap.put("HuFa", 2);
positionMap.put("ZhangLao", 3);
positionMap.put("TangZhu", 4);
positionMap.put("JingYing", 5);
positionMap.put("BangZhong", 6);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(); // 读取帮友人数
scanner.nextLine(); // 消耗换行符
List<Member> members = new ArrayList<>();
for (int i = 1; i <= n; i++) {
String name = scanner.next(); // 读取名字
String originalPosition = scanner.next(); // 读取原职位
long contribution = scanner.nextLong(); // 读取帮贡
int level = scanner.nextInt(); // 读取等级
scanner.nextLine(); // 消耗换行符
members.add(new Member(name, originalPosition, contribution, level, i)); // 创建成员对象并添加到列表中
}
scanner.close();
// 按帮贡和输入顺序排序(忽略前三个帮主和副帮主)
Collections.sort(members.subList(3, n), new Comparator<Member>() {
public int compare(Member x, Member y) {
if (x.contribution == y.contribution) {
return Integer.compare(x.index, y.index);
} else {
return Long.compare(y.contribution, x.contribution);
}
}
});
// 根据排序后的结果分配新职位
for (int i = 0; i < n; i++) {
if (i == 0) {
members.get(i).newPosition = "BangZhu"; // 帮主
} else if (i == 1 || i == 2) {
members.get(i).newPosition = "FuBangZhu"; // 副帮主
} else if (i == 3 || i == 4) {
members.get(i).newPosition = "HuFa"; // 护法
} else if (i >= 5 && i <= 8) {
members.get(i).newPosition = "ZhangLao"; // 长老
} else if (i >= 9 && i <= 15) {
members.get(i).newPosition = "TangZhu"; // 堂主
} else if (i >= 16 && i <= 40) {
members.get(i).newPosition = "JingYing"; // 精英
} else {
members.get(i).newPosition = "BangZhong"; // 帮众
}
}
// 按新职位、等级和输入顺序排序
Collections.sort(members, new Comparator<Member>() {
public int compare(Member x, Member y) {
if (positionMap.get(x.newPosition).equals(positionMap.get(y.newPosition))) {
if (x.level == y.level) {
return Integer.compare(x.index, y.index);
}
return Integer.compare(y.level, x.level);
}
return Integer.compare(positionMap.get(x.newPosition), positionMap.get(y.newPosition));
}
});
// 输出结果
for (Member member : members) {
System.out.println(member.name + " " + member.newPosition + " " + member.level);
}
}
}
P1591 阶乘数码
import java.math.BigInteger;
import java.util.Scanner;
/**
* @Author HeShen.
* @Date 2024/3/16 21:03
*/
//首先求出阶乘,然后int转String查找数码出现次数即可
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int t = input.nextInt();int[] p = new int[t];char[] q = new char[t];
for (int i = 0; i < t; i++) {
p[i] = input.nextInt();
q[i] = input.next().charAt(0);
}
for (int i = 0; i < t; i++) {
String temp = String.valueOf(func(p[i]));
System.out.println(find(temp, q[i]));
}
}
public static int find(String s, char a){
int count = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == a) {
count++;
}
}
return count;
}
public static BigInteger func(int num){
BigInteger n = BigInteger.valueOf(num);
if (num == 1) return BigInteger.valueOf(num);
return n.multiply(func(num - 1));
}
}
P1249 最大乘积
解题步骤
数组初始化:
int[] a
:用于存储分解的自然数。int[] s
:用于存储高精度计算结果。int len
:记录当前高精度数的长度。特殊情况处理:
- 当
n == 3
和n == 4
时,直接输出分解方案和乘积。贪心分解:
- 从 2 开始逐步增加,将其加入分解方案,直到剩余的数不足以分配给下一个自然数。
- 通过
sum
和tot
变量记录当前和和已分解的数的总个数。调整分解:
- 如果分解后总和
sum
大于n + 1
,移除一个数。- 如果分解后总和
sum
等于n + 1
,调整分解方案以确保所有数不同。高精度乘法:
mul(int x)
方法用于将高精度数s
乘以x
。- 使用数组
s
存储乘法结果,并处理每位上的进位。输出:
- 输出分解方案。
- 输出高精度乘法结果。
import java.util.Scanner;
public class Main {
// 数组a用于存储分解后的各个部分
static int[] a = new int[10001];
// 数组s用于高精度乘法计算
static int[] s = new int[10001];
// 用于记录当前高精度数的长度
static int len = 1;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取输入的整数n
int n = scanner.nextInt();
scanner.close();
// 特殊情况处理,当n为3和4时直接输出结果
if (n == 3) {
System.out.println("1 2");
System.out.println("2");
return;
}
if (n == 4) {
System.out.println("1 3");
System.out.println("3");
return;
}
// 初始化高精度乘法的结果,s[0]未用,s[1]置为1
s[0] = s[1] = 1;
int sum = 0, tot = 0;
// 贪心分解,将n尽量分解成1, 2, 3, ..., k这些数
for (int i = 2; sum < n; sum += i, i++) {
a[++tot] = i;
}
// 根据剩余情况进行调整
if (sum > n + 1) {
a[sum - n - 1] = 0; // 移除一个数
} else if (sum == n + 1) {
a[tot]++; // 增加最后一个数
a[1] = 0; // 移除第一个数
}
// 输出分解方案并计算乘积
for (int i = 1; i <= tot; i++) {
if (a[i] != 0) {
System.out.print(a[i] + " ");
mul(a[i]); // 高精度乘法
}
}
System.out.println();
// 输出高精度乘法结果
for (int i = len; i >= 1; i--) {
System.out.print(s[i]);
}
System.out.println();
}
// 高精度乘法,将高精度数s乘以x
static void mul(int x) {
// 逐位乘以x
for (int i = 1; i <= len; i++) {
s[i] *= x;
}
// 处理进位
for (int i = 1; i <= len; i++) {
s[i + 1] += s[i] / 10;
s[i] %= 10;
}
// 处理最高位可能产生的新进位
while (s[len + 1] > 0) {
len++;
s[len + 1] += s[len] / 10;
s[len] %= 10;
}
}
}
P1045 [NOIP2003 普及组] 麦森数
解题步骤
解决方案
- 计算位数:利用对数公式来计算
2^P - 1
的位数。- 计算最后 500 位数字:使用
BigInteger
进行高精度运算。步骤
- 读取输入的 P。
- 使用对数公式计算
2^P - 1
的位数。- 使用
BigInteger
计算2^P - 1
的值,并取其最后 500 位。- 格式化输出结果。
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取输入的 P
int P = scanner.nextInt();
// 计算 2^P - 1 的位数
int numDigits = (int) Math.floor(P * Math.log10(2)) + 1;
// 使用 BigInteger 计算 2^P - 1
BigInteger two = BigInteger.valueOf(2);
BigInteger mersenneNumber = two.pow(P).subtract(BigInteger.ONE);
// 获取最后 500 位
BigInteger modulus = BigInteger.TEN.pow(500);
BigInteger last500Digits = mersenneNumber.mod(modulus);
// 将最后 500 位转换为字符串,并补足 500 位
String last500Str = last500Digits.toString();
while (last500Str.length() < 500) {
last500Str = "0" + last500Str;
}
// 输出位数
System.out.println(numDigits);
// 输出最后 500 位,每行 50 位
for (int i = 0; i < 500; i += 50) {
System.out.println(last500Str.substring(i, i + 50));
}
scanner.close();
}
}