All-Ukrainian School Olympiad in InformaticsE. Points(数学)

60 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第20天,点击查看活动详情
本文已参与「新人创作礼」活动,一 起开启掘金创作之路。

题目

image.png 中文大意

输入一个n表示有n个点让我们求出所有点对之间距离的平方和

解法

由我们之前学过的知识可以知道2=(x1x2)2+(y1y2)2距离^2 = (x_1-x_2)^2 + (y_1-y_2)^2所以为了求所有点对的方程我们就可以知道resres=inj=i+1n(xixj)2+(yiyj)2\sum_i^n\sum_{j=i+1}^n(x_i-x_j)^2 + (y_i-y_j)^2 然后我们拆平方式就可以得到这样的一个公式inj=i+1nxi2+xj2+yi2+yj22(xixj+yiyj)\sum_i^n\sum_{j=i+1}^nx_i^2+x_j^2 +y_i^2+y_j^2-2(x_ix_j+y_iy_j)
我们再继续拆分就得到了(n1)(xi2+xj2+yi2+yj2)2inj=i+1n(xixj+yiyj)(n-1)*(x_i^2+x_j^2+y_i^2+y_j^2)-2\sum_i^n\sum_{j=i+1}^n(x_ix_j+y_iy_j)然后我们对这个式子进行分析我们就可以发现对于每一个有xix_i参与的式子的值是xij=1+1nxjx_i*\sum_{j=1+1}^nx_j所有对于这个式子我们用一个前缀和去处理即可这样我们的答案就可以求出来了

#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
using namespace std;
using ll = long long;
#define int long long
#define endl '\n'
#define pb push_back
#define NO cout << "NO" << endl;
#define YES cout << "YES" << endl;
#define fi first
#define se second
#define all(x) (x).begin(),(x).end()
#define rep(i,n) for(int i = 1; i <= n; i++)
typedef pair<int,int> PII;
const int N = 2e5 + 10;
int a[N],b[N];
int sa[N],sb[N];
void solve()
{
   int n; cin >> n;
   int res = 0;
   rep(i,n) {
      cin >> a[i] >> b[i];
      res += (a[i] * a[i] + b[i] * b[i] )* (n - 1);
   }
   for(int i = n; i >= 1; i--) sa[i] = sa[i + 1] + a[i];
   for(int i = n; i >= 1; i--) sb[i] = sb[i + 1] + b[i];
   rep(i,n) res -= 2*(a[i] * sa[i+1] + b[i] * sb[i+1]);
   cout << res << endl;   
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    // int T;cin >> T;
    // while ( T -- )
    solve();
    return 0;
}