题意: 给定一个长度为 n n n的坐标序列 a a a,以及一个坐标 M 0 M_0 M0 M i M_i Mi M i 1 M_{i-1} Mi1 a { ( i 1 ) m o d <mtext>   </mtext> n } a_{\{(i-1)mod\ n\}} a{(i1)mod n}对称,求 M j M_j Mj坐标

题解: 我们先写几项出来:
M 1 = <mtext>                           </mtext> 2 a 0 M 0 M_1 = \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 2*a_0-M_0 M1=                         2a0M0
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=2a1M1=2a12a0+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=2a2M2=2a22a1+2a0M0
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=2a3M3=2a32a2+2a12a0+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=2a4M4=2a42a3+2a22a1+2a0M0

这里可以看出来是有前缀和的思想,处理的是一加一减的前缀。
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 2k个,那么无需计算,连续的前缀为 2 k + 1 2*k+1 2k+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;
}