前言
使用java,根据官方模拟考试的试题列表刷题 试题清单
目前只更新了前三题的思路,并且第三题跟着找到的满分答案但只得了60分(求佬指点),后面两题先放一放,随缘更新~
202309
满分思路:累加操作dx和dy,对每个初始坐标进行坐标加法即可
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(), m = scanner.nextInt();
int tx = 0, ty = 0;
for (int i = 0; i < n; i++) {
tx += scanner.nextInt();
ty += scanner.nextInt();
}
for (int i = 0; i < m; i++)
System.out.println((scanner.nextInt() + tx) + " " + (scanner.nextInt() + ty));
}
}
(1)80分思路:运行超时。使用二维数组记录每个操作序列;对于每个查询,统计指定操作得总拉伸和总旋转,计算变换后结果
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(), m = scanner.nextInt();
double[][] actions = new double[n + 1][2];
for (int i = 1; i <= n; i++) {
actions[i][0] = scanner.nextDouble();
actions[i][1] = scanner.nextDouble();
}
for (int i = 0; i < m; i++) {
int l = scanner.nextInt(), r = scanner.nextInt();
double x = scanner.nextDouble(), y = scanner.nextDouble();
double k = 1, theta = 0;
for (int t = l; t <= r; t++) {
double type = actions[t][0], temp = actions[t][1];
if (type == 1) k *= temp;
else if (type == 2) theta += temp;
}
double tempX = x * k, tempY = y * k;
x = tempX * Math.cos(theta) - tempY * Math.sin(theta);
y = tempX * Math.sin(theta) + tempY * Math.cos(theta);
System.out.println(x + " " + y);
}
}
}
(2)100分思路:两个double[]分别记录拉伸前缀积和旋转前缀和;对于每个查询,进行ks[r]-ks[l-1]的拉伸和thetas[r]-thetas[l-1]的旋转。
设计:初始化ks[0]为1,thetas[0]为0
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(), m = scanner.nextInt();
double[] ks = new double[n + 1], thetas = new double[n + 1];
ks[0] = 1;
thetas[0] = 0;
for (int i = 1; i <= n; i++) {
int type = scanner.nextInt();
if (type == 1) {
ks[i] = ks[i - 1] * scanner.nextDouble();
thetas[i] = thetas[i - 1];
} else if (type == 2) {
ks[i] = ks[i - 1];
thetas[i] = thetas[i - 1] + scanner.nextDouble();
}
}
for (int i = 0; i < m; i++) {
int l = scanner.nextInt(), r = scanner.nextInt();
double k = ks[r] / ks[l - 1], theta = thetas[r] - thetas[l - 1];
double x = scanner.nextDouble() * k, y = scanner.nextDouble() * k;
System.out.println((x * Math.cos(theta) - y * Math.sin(theta))
+ " " + (x * Math.sin(theta) + y * Math.cos(theta)));
}
}
}
(1)50分思路:参考csdn一位博主的思路,利用导数的定义求解。设置微小变量,计算两函数结果之差,求得一阶导四舍五入取整
(2)60分思路:根据csdn上c++满分思路实现,但最后只拿了60,还没找出原因(求大佬指导)。List<long[]>存储一个多项式,各项之间为加法,其中一个long[]的第一项为系数,其余为下标对应自变量的指数;使用Deque<List<long[]>>实现栈,进行后缀表达式求解;求导舍弃常数项,只对含求导量的项计算
注意:
①该题中没有除法;
②使用long存储,结果可能大于int;
③每次的结果都要取余;
④java中使用switch的case ->{}用法会编译出错
import java.util.*;
public class Main {
static long mod = (long) Math.pow(10, 9) + 7;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt(), m = scanner.nextInt();
scanner.nextLine(); // 清空缓存换行符
String[] function = scanner.nextLine().split("\\s+"); // 读取表达式
Deque<List<long[]>> stack = new ArrayDeque<>(); // 表达式栈
for (String s : function) {
if (s.equals("*") || s.equals("/") || s.equals("+") || s.equals("-")) {
List<long[]> tempListB = stack.pollFirst(), tempListA = stack.pollFirst();
if (tempListA != null && tempListB != null) {
List<long[]> tempList = new ArrayList<>();
switch (s) {
case "*" :
for (long[] tempA : tempListA) {
for (long[] tempB : tempListB) {
long[] temp = new long[n + 1];
temp[0] = tempA[0] * tempB[0];
for (int i = 1; i <= n; i++) temp[i] = tempA[i] + tempB[i];
tempList.add(temp);
}
}
break;
case "+" :
tempList.addAll(tempListA);
tempList.addAll(tempListB);
break;
case "-" :
tempList.addAll(tempListA);
for (long[] tempB : tempListB) {
tempB[0] = -tempB[0];
tempList.add(tempB);
}
break;
default:
break;
}
stack.offerFirst(tempList);
}
} else {
long[] temp = new long[n + 1];
if (s.charAt(0) == 'x') {
temp[0] = 1;
temp[s.charAt(1) - '0']++;
} else {
temp[0] = Long.parseLong(s);
}
List<long[]> tempList = new ArrayList<>();
tempList.add(temp);
stack.offerFirst(tempList);
}
}
List<long[]> resFunction = stack.pollFirst(); // 结果表达式
for (int i = 0; i < m; i++) {
int code = scanner.nextInt(); // 求导编号
long[] values = new long[n + 1];
for (int k = 1; k <= n; k++) { // 变量值
values[k] = scanner.nextLong();
}
long res = 0;
if (resFunction != null) {
for (long[] item : resFunction) {
if (item[code] == 0) continue; // 常数项
long tempRes = (item[0] * item[code]) % mod;
for (int t = 1; t <= n; t++) {
if (t == code) tempRes = (tempRes * (long) Math.pow(values[t], item[t] - 1)) % mod;
else if (item[t] != 0) tempRes = (tempRes * (long) Math.pow(values[t], item[t])) % mod; //该变量存在
}
res = (res + tempRes) % mod;
}
}
System.out.println(res < 0 ? res + mod : res);
}
}
}
202309总结
1、第一题基本没难度,第二题利用前缀积和前缀和优化,第三题使用数组存储一项的系数和指数
2、第三题要对每个结果都取模
3、java中switch的case->{}用法(java12)会编译不通过