Codeforces 24C

题意: 给定一个长度为 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   n } a_{\{(i-1)mod\ n\}} a{(i1)mod n}对称,求 M j M_j Mj坐标

题解: 我们先写几项出来:
M 1 =                           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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值