CSP认证-202309

前言

        使用java,根据官方模拟考试的试题列表刷题 试题清单

        目前只更新了前三题的思路,并且第三题跟着找到的满分答案但只得了60分(求佬指点),后面两题先放一放,随缘更新~

202309

202309-1 坐标变换(其一)

满分思路:累加操作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));
    }
}

202309-2 坐标变换(其二)

(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)));
        }
    }
}

202309-3 梯度求解

(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)会编译不通过

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值