更多 CSP 认证考试题目题解可以前往:CSP-CCF 认证考试真题题解
原题链接: 202309-1 坐标变换(其一)
时间限制: 1.0s
内存限制: 512.0MB
问题描述
对于平面直角坐标系上的坐标 ( x , y ) (x, y) (x,y),小 P 定义了一个包含 n n n 个操作的序列 T = ( t 1 , t 2 , ⋯ , t n ) T = ( t_1, t_2, \cdots, t_n ) T=(t1,t2,⋯,tn)。其中每个操作 t i t_i ti( 1 ≤ i ≤ n 1 \le i \le n 1≤i≤n)包含两个参数 d x i dx_i dxi 和 d y i dy_i dyi,表示将坐标 ( x , y ) (x, y) (x,y) 平移至 ( x + d x i , y + d y i ) (x + dx_i, y + dy_i) (x+dxi,y+dyi) 处。
现给定 m m m 个初始坐标,试计算对每个坐标 ( x j , y j ) (x_j, y_j) (xj,yj)( 1 ≤ j ≤ m 1 \le j \le m 1≤j≤m)依次进行 T T T 中 n n n 个操作后的最终坐标。
输入格式
从标准输入读入数据。
输入共 n + m + 1 n+m+1 n+m+1 行。
输入的第一行包含空格分隔的两个正整数 n n n 和 m m m,分别表示操作和初始坐标个数。
接下来 n n n 行依次输入 n n n 个操作,其中第 i i i( 1 ≤ i ≤ n 1 \le i \le n 1≤i≤n)行包含空格分隔的两个整数 d x i dx_i dxi、 d y i dy_i dyi。
接下来 m m m 行依次输入 m m m 个坐标,其中第 j j j( 1 ≤ j ≤ m 1 \le j \le m 1≤j≤m)行包含空格分隔的两个整数 x j x_j xj、 y j y_j yj。
输出格式
输出到标准输出中。
输出共 m m m 行,其中第 j j j( 1 ≤ j ≤ m 1 \le j \le m 1≤j≤m)行包含空格分隔的两个整数,表示初始坐标 ( x j , y j ) (x_j, y_j) (xj,yj) 经过 n n n 个操作后的位置。
样例输入
3 2
10 10
0 0
10 -20
1 -1
0 0
样例输出
21 -11
20 -10
样例说明
第一个坐标 ( 1 , − 1 ) (1, -1) (1,−1) 经过三次操作后变为 ( 21 , − 11 ) (21, -11) (21,−11);第二个坐标 ( 0 , 0 ) (0, 0) (0,0) 经过三次操作后变为 ( 20 , − 10 ) (20, -10) (20,−10)。
评测用例规模与约定
全部的测试数据满足: n , m ≤ 100 n, m \le 100 n,m≤100,所有输入数据( x , y , d x , d y x, y, dx, dy x,y,dx,dy)均为整数且绝对值不超过 100000 100000 100000。
题解
对于每个初始坐标 ( x j , y j ) (x_j,y_j) (xj,yj),输出的答案为 ( x j + ∑ i = 1 n d x i , y j + ∑ i = 1 n d y i ) \left(x_j+\sum\limits_{i=1}^ndx_i,y_j+\sum\limits_{i=1}^ndy_i\right) (xj+i=1∑ndxi,yj+i=1∑ndyi)。
在读入 d x , d y dx,dy dx,dy 过程中将其求和,然后每个坐标直接计算即可。
时间复杂度: O ( n + m ) \mathcal{O}(n+m) O(n+m)。
参考代码(0ms,2.921MB)
/*
Created by Pujx on 2024/2/5.
*/
#pragma GCC optimize(2, 3, "Ofast", "inline")
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
//#define int long long
//#define double long double
using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
#define inf (int)0x3f3f3f3f3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define yn(x) cout << (x ? "yes" : "no") << endl
#define Yn(x) cout << (x ? "Yes" : "No") << endl
#define YN(x) cout << (x ? "YES" : "NO") << endl
#define mem(x, i) memset(x, i, sizeof(x))
#define cinarr(a, n) for (int i = 1; i <= n; i++) cin >> a[i]
#define cinstl(a) for (auto& x : a) cin >> x;
#define coutarr(a, n) for (int i = 1; i <= n; i++) cout << a[i] << " \n"[i == n]
#define coutstl(a) for (const auto& x : a) cout << x << ' '; cout << endl
#define all(x) (x).begin(), (x).end()
#define md(x) (((x) % mod + mod) % mod)
#define ls (s << 1)
#define rs (s << 1 | 1)
#define ft first
#define se second
#define pii pair<int, int>
#ifdef DEBUG
#include "debug.h"
#else
#define dbg(...) void(0)
#endif
const int N = 2e5 + 5;
//const int M = 1e5 + 5;
const int mod = 998244353;
//const int mod = 1e9 + 7;
//template <typename T> T ksm(T a, i64 b) { T ans = 1; for (; b; a = 1ll * a * a, b >>= 1) if (b & 1) ans = 1ll * ans * a; return ans; }
//template <typename T> T ksm(T a, i64 b, T m = mod) { T ans = 1; for (; b; a = 1ll * a * a % m, b >>= 1) if (b & 1) ans = 1ll * ans * a % m; return ans; }
int a[N];
int n, m, t, k, q;
void work() {
cin >> n >> m;
int X = 0, Y = 0;
for (int i = 1, dx, dy; i <= n; i++) cin >> dx >> dy, X += dx, Y += dy;
for (int i = 1, x, y; i <= m; i++) {
cin >> x >> y;
cout << x + X << ' ' << y + Y << endl;
}
}
signed main() {
#ifdef LOCAL
freopen("C:\\Users\\admin\\CLionProjects\\Practice\\data.in", "r", stdin);
freopen("C:\\Users\\admin\\CLionProjects\\Practice\\data.out", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int Case = 1;
//cin >> Case;
while (Case--) work();
return 0;
}
/*
_____ _ _ _ __ __
| _ \ | | | | | | \ \ / /
| |_| | | | | | | | \ \/ /
| ___/ | | | | _ | | } {
| | | |_| | | |_| | / /\ \
|_| \_____/ \_____/ /_/ \_\
*/
关于代码的亿点点说明:
- 代码的主体部分位于
void work()
函数中,另外会有部分变量申明、结构体定义、函数定义在上方。#pragma ...
是用来开启 O2、O3 等优化加快代码速度。- 中间一大堆
#define ...
是我习惯上的一些宏定义,用来加快代码编写的速度。"debug.h"
头文件是我用于调试输出的代码,没有这个头文件也可以正常运行(前提是没定义DEBUG
宏),在程序中如果看到dbg(...)
是我中途调试的输出的语句,可能没删干净,但是没有提交上去没有任何影响。ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
这三句话是用于解除流同步,加快输入cin
输出cout
速度(这个输入输出流的速度很慢)。在小数据量无所谓,但是在比较大的读入时建议加这句话,避免读入输出超时。如果记不下来可以换用scanf
和printf
,但使用了这句话后,cin
和scanf
、cout
和printf
不能混用。- 将
main
函数和work
函数分开写纯属个人习惯,主要是为了多组数据。