第 50 届 ICPC 国际大学生程序设计竞赛区域赛沈阳站 K 题思路分享(数学)
https://codeforces.com/gym/106252/problem/K
题意概述
给定笛卡尔平面上 \(n\) 只青蛙,当青蛙 \(i\) 被刺激时,会选择另一只青蛙 \(j\),跳跃到当前位置与青蛙 \(j\) 位置的对称点上,青蛙 \(j\) 成为下一个被刺激的青蛙.
给定 \(n\) 只青蛙的起点 \(P\) 和终点 \(Q\),以及第一只被刺激的青蛙,求出最后一只被刺激的青蛙,保证有解.
\(2\le n \le 10^5\).
思路
青蛙跳跃的过程非常复杂,考虑寻找与坐标相关的某个不变量.
当青蛙 \(i\) 跳跃到与青蛙 \(j\) 的对称点上时,\(x'=2x_j-x_i\),\(\Delta x = 2x_j-2x_i\).
\(\Delta x\) 系数是一致的,考虑构造 \(\phi(i) = \sum{x}-2x_i\).
跳跃前,被刺激青蛙为 \(i\),\(\phi(i)=\sum{x}-2x_i\);跳跃后,被刺激青蛙为 \(j\),\(\phi(j)=\sum{x}+\Delta x-2x_j=\sum{x}-2x_i=\phi(i)\).
于是 \(\phi(i)\) 为不变量,记第一只被刺激青蛙为 \(s\),最后一只为 \(t\),解
\[\begin{cases}
\sum{P_x} - 2x_s = \sum{Q_x}-2x_t \\[1em]
\sum{P_y} - 2y_s = \sum{Q_y}-2y_t
\end{cases}
\]
得
\[\begin{cases}
x_t = \dfrac{\sum{Q_x}-\sum{P_x}+2x_s}{2} \\[1em]
y_t = \dfrac{\sum{Q_y}-\sum{P_y}+2y_s}{2}
\end{cases}
\]
找到这样的终点坐标即可.
时间复杂度 \(\mathcal{O}(n)\).
代码
//author:kzssCCC
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve(){
int n,s;
cin >> n >> s;
vector<pair<ll,ll>> P(n+1),Q(n+1);
ll sumpx=0,sumqx=0,sumpy=0,sumqy=0;
for (int i=1;i<=n;i++){
cin >> P[i].first >> P[i].second >> Q[i].first >> Q[i].second;
sumpx += P[i].first;
sumpy += P[i].second;
sumqx += Q[i].first;
sumqy += Q[i].second;
}
ll tx = (sumqx-sumpx+2*P[s].first)/2;
ll ty = (sumqy-sumpy+2*P[s].second)/2;
for (int i=1;i<=n;i++){
if (tx==Q[i].first && ty==Q[i].second){
cout << i << '\n';
return;
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t = 1;
// cin >> t;
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号