【CSP】202309-2_坐标变换(其二)Python实现

文章目录

    • @[toc]
      • 试题编号
      • 试题名称
      • 时间限制
      • 内存限制
      • 问题描述
      • 输入格式
      • 输出格式
      • 样例输入
      • 样例输出
      • 样例说明
      • 评测用例规模与约定
      • 评分方式
      • 提示
      • `Python`实现

试题编号

202309-2

试题名称

坐标变换(其二)

时间限制

2.0s

内存限制

512.0MB

问题描述

  • 对于平面直角坐标系上的坐标 ( x , y ) (x , y) (x,y),小 P P P定义了如下两种操作

    • 拉伸 k k k倍:横坐标 x x x变为 k x kx kx,纵坐标 y y y变为 k y ky ky
    • 旋转 θ \theta θ:将坐标 ( x , y ) (x , y) (x,y)绕坐标原点 ( 0 , 0 ) (0 , 0) (0,0)逆时针旋转 θ \theta θ弧度 ( 0 ≤ θ < 2 π ) (0 \leq \theta < 2 \pi) (0θ<2π),易知旋转后的横坐标为 x cos ⁡ θ − y sin ⁡ θ x \cos{\theta} - y \sin{\theta} xcosθysinθ,纵坐标为 x sin ⁡ θ + y cos ⁡ θ x \sin{\theta} + y \cos{\theta} xsinθ+ycosθ
  • 设定好了包含 n n n个操作的序列 ( t 1 , t 2 , ⋯   , t n ) (t_{1} , t_{2} , \cdots , t_{n}) (t1,t2,,tn)后,小 P P P又定义了如下查询

    • i   j   x   y i \ j \ x \ y i j x y:坐标 ( x , y ) (x , y) (x,y)经过操作 t i , ⋯   , t j ( 1 ≤ i ≤ j ≤ n ) t_{i} , \cdots , t_{j} (1 \leq i \leq j \leq n) ti,,tj(1ijn)后的新坐标
  • 对于给定的操作序列,试计算 m m m个查询的结果


输入格式

  • 从标准输入读入数据
  • 输入共 n + m + 1 n + m + 1 n+m+1
  • 输入的第一行包含空格分隔的两个正整数 n n n m m m,分别表示操作和查询个数
  • 接下来 n n n行依次输入 n n n个操作,每行包含空格分隔的一个整数(操作类型)和一个实数( k k k θ \theta θ),形如 1 k 1k 1k(表示拉伸 k k k倍)或 2 θ 2 \theta 2θ(表示旋转 θ \theta θ
  • 接下来 m m m行依次输入 m m m个查询,每行包含空格分隔的四个整数 i i i j j j x x x y y y,含义如前文所述

输出格式

  • 输出到标准输出中
  • 输出共 m m m行,每行包含空格分隔的两个实数,表示对应查询的结果

样例输入

10 5
2 0.59
2 4.956
1 0.997
1 1.364
1 1.242
1 0.82
2 2.824
1 0.716
2 0.178
2 4.094
1 6 -953188 -946637
1 9 969538 848081
4 7 -114758 522223
1 9 -535079 601597
8 8 159430 -511187

样例输出

-1858706.758 -83259.993
-1261428.46 201113.678
-75099.123 -738950.159
-119179.897 -789457.532
114151.88 -366009.892

样例说明

  • 第五个查询仅对输入坐标使用了操作八:拉伸 0.716 0.716 0.716
  • 横坐标: 159430 × 0.716 = 114151.88 159430 \times 0.716 = 114151.88 159430×0.716=114151.88
  • 纵坐标: − 511187 × 0.716 = − 366009.892 -511187 \times 0.716 = -366009.892 511187×0.716=366009.892
  • 由于具体计算方式不同,程序输出结果可能与真实值有微小差异,样例输出仅保留了三位小数

评测用例规模与约定

  • 80 % 80\% 80%的测试数据满足: n , m ≤ 1000 n , m \leq 1000 n,m1000
  • 全部的测试数据满足
    • n , m ≤ 100000 n , m \leq 100000 n,m100000
    • 输入的坐标均为整数且绝对值不超过 1000000 1000000 1000000
    • 单个拉伸操作的系数 k ∈ [ 0.5 , 2 ] k \in [0.5 , 2] k[0.5,2]
    • 任意操作区间 t i , ⋯   , t j ( 1 ≤ i ≤ j ≤ n ) t_{i} , \cdots , t_{j} (1 \leq i \leq j \leq n) ti,,tj(1ijn)内拉伸系数 k k k的乘积在 [ 0.001 , 1000 ] [0.001 , 1000] [0.001,1000]范围内

评分方式

  • 如果你输出的浮点数与参考结果相比,满足绝对误差不大于 0.1 0.1 0.1,则该测试点满分,否则不得分

提示

  • C/C++:建议使用double类型存储浮点数,并使用scanf("%lf", &x);进行输入,printf("%f", x);输出,也可以使用cincout输入输出浮点数;#include 后可使用三角函数cos()sin()
  • Python:直接使用print(x)即可输出浮点数xfrom math import cos, sin后可使用相应三角函数
  • Java:建议使用double类型存储浮点数,可以使用System.out.print(x);进行输出;可使用Math.cos()Math.sin()调用三角函数

Python实现

from math import sin, cos, sqrt, atan2

n, m = map(int, input().split())

op = []
for _ in range(n):
    num1, num2 = map(float, input().split())
    num1 = int(num1)

    if num1 == 1:
        op.append([num2, 0])
    else:
        op.append([1, num2])

for i in range(1, n):
    op[i][0] *= op[i - 1][0]
    op[i][1] += op[i - 1][1]

for _ in range(m):
    i, j, x, y = map(int, input().split())
    i -= 1
    j -= 1

    r = sqrt(x * x + y * y)
    theta = atan2(y, x)

    r *= op[j][0]
    theta += op[j][1]

    if i:
        r /= op[i - 1][0]
        theta -= op[i - 1][1]

    x = r * cos(theta)
    y = r * sin(theta)

    print(x, y)

你可能感兴趣的:(刷题,#,CSP,刷题,CSP,Python)