题意: 给定一个长度为 n n n的坐标序列 a a a,以及一个坐标 M 0 M_0 M0。 M i M_i Mi和 M i − 1 M_{i-1} Mi−1以 a { ( i − 1 ) m o d n } a_{\{(i-1)mod\ n\}} a{(i−1)mod n}对称,求 M j M_j Mj坐标
题解: 我们先写几项出来:
①
M
1
=
2
∗
a
0
−
M
0
M_1 = \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2*a_0-M_0
M1= 2∗a0−M0
②
M
2
=
2
∗
a
1
−
M
1
=
2
∗
a
1
−
2
∗
a
0
+
M
0
M_2 = 2*a_1-M_1=2*a_1-2*a_0+M_0
M2=2∗a1−M1=2∗a1−2∗a0+M0
③
M
3
=
2
∗
a
2
−
M
2
=
2
∗
a
2
−
2
∗
a
1
+
2
∗
a
0
−
M
0
M_3 = 2*a_2-M_2=2*a_2-2*a_1+2*a_0-M_0
M3=2∗a2−M2=2∗a2−2∗a1+2∗a0−M0
④
M
4
=
2
∗
a
3
−
M
3
=
2
∗
a
3
−
2
∗
a
2
+
2
∗
a
1
−
2
∗
a
0
+
M
0
M_4 = 2*a_3-M_3=2*a_3-2*a_2+2*a_1-2*a_0+M_0
M4=2∗a3−M3=2∗a3−2∗a2+2∗a1−2∗a0+M0
⑤
M
5
=
2
∗
a
4
−
M
4
=
2
∗
a
4
−
2
∗
a
3
+
2
∗
a
2
−
2
∗
a
1
+
2
∗
a
0
−
M
0
M_5 = 2*a_4-M_4=2*a_4-2*a_3+2*a_2-2*a_1+2*a_0-M_0
M5=2∗a4−M4=2∗a4−2∗a3+2∗a2−2∗a1+2∗a0−M0
这里可以看出来是有前缀和的思想,处理的是一加一减的前缀。
即
p
r
e
[
0
]
=
a
[
0
]
,
p
r
e
[
1
]
=
a
[
0
]
−
a
[
1
]
,
p
r
e
[
2
]
=
a
[
0
]
−
a
[
1
]
+
a
[
2
]
,
pre[0] = a[0],pre[1]=a[0]-a[1],pre[2]=a[0]-a[1]+a[2],
pre[0]=a[0],pre[1]=a[0]−a[1],pre[2]=a[0]−a[1]+a[2],以此类推。
由于有取模的影响,那么先求处理出有多少完整的前缀
n
n
n,
同时
n
n
n是奇数,故连续的
n
n
n个元素最多只能存在一组,其他都会相互抵消。
故我们只需处理三部分:
1.
1.
1. 连续的前缀部分为
2
∗
k
2*k
2∗k个,那么无需计算,连续的前缀为
2
∗
k
+
1
2*k+1
2∗k+1个,那么只需统计一个即可。
2.
2.
2. 除去连续的前缀部分,
a
a
a元素的部分。
3.
M
0
3. M_0
3.M0
处理的时候要注意存储的是加
a
0
a_0
a0,减
a
1
a_1
a1,即加
a
偶
数
a_{偶数}
a偶数,减
a
奇
数
a_{奇数}
a奇数。
所以需要计算一下位置来确定当前是否需要加负号。
代码:
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef long long ll;
typedef pair<ll, ll> PLL;
const int N = 1e5 + 10;
PLL a[N], all[N], M;
ll n, j;
int main()
{
scanf("%lld%lld", &n, &j);
scanf("%lld%lld", &M.x, &M.y);
for(int i = 0; i < n; i++) scanf("%lld%lld", &a[i].x, &a[i].y);
all[0] = a[0];
for(int i = 1; i < n; i++) {
if(i & 1) all[i].x = all[i - 1].x - a[i].x, all[i].y = all[i - 1].y - a[i].y;
else all[i].x = all[i - 1].x + a[i].x, all[i].y = all[i - 1].y + a[i].y;
}
int cnt = ((j / n) & 1);
int t = (j - 1) % n;
int pM = (j & 1) ? -1 : 1;
int pS = (t & 1) ? -1 : 1;
int pF = -pS;
if(j % n == 0) pS = 0, pF = 1;
ll rx = pM * M.x + 2ll * (cnt * pF * all[n - 1].x + pS * all[t].x);
ll ry = pM * M.y + 2ll * (cnt * pF * all[n - 1].y + pS * all[t].y);
printf("%lld %lld\n", rx, ry);
return 0;
}