[数学推导] aw3782. 点(推公式+数学推导+数学证明+CF76E)
Posted Ypuyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[数学推导] aw3782. 点(推公式+数学推导+数学证明+CF76E)相关的知识,希望对你有一定的参考价值。
1. 题目来源
链接:3782. 点
2. 题目解析
两点之间距离,为了不重复计算,给每个点编号,并定义其有序性。然后发现,x
和 y
完全可以独立计算。然后推公式即可,公式中有重要的优化需要谨记。
但其实,从分析的角度上来考虑,单独考虑一个点与其它所有点的所得贡献。
- 两两组队,每个
x^2
出现n-1
次是显然的。简单画个图,列举情况就懂了。故当前点x^2
贡献了(n-1)*x[i]*x[i]
次,将平方的总贡献累加即可。 - 同理其中出现的
2x1*x2
的情况,固定一个x1
,那么有n-1
个xi
将于x1
配对,提取公因式的话,就是除过x1
的所有数均要与x1
相乘,这个维护一个总数,减去当前数x1
即可得到。 - 同时,
2x1*x2
的部分,其实是被计算了两次,即在考虑x1
点时,考虑了其它各点,在考虑其它各点时,又考虑了x1
这个点,所以是重复计算了一次,除 2 就行了。 - 也可以用笔记中的,将
2x1*x2
这部分的有序性消除,变成xi*xj
无序,即可。
或者说,我们在考虑 (x1,y1)
点时,仅考虑这个点所带来的贡献,即它在所有的配对中,一共贡献了 n-1
个 x1*x1
,n-1
个 y1*y1
,在 2x1*x2
这个部分,这其实是由两个点所带来的,我们仅取和自己相关的一部分,即仅计算一个 x1*x2
。
好好理解就行,理解不了就直接上数学公式就行了。
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)
完美的数学公式推导
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5+5;
int n;
int x[N], y[N];
LL cal(int x[]) {
LL s1 = 0, s2 = 0;
for (int i = 0; i < n; i ++ ) s1 += x[i] * x[i], s2 += x[i];
return (n - 1) * s1 - (s2 * s2 - s1);
}
int main() {
cin >> n;
for (int i = 0; i < n; i ++ ) cin >> x[i] >> y[i];
cout << cal(x) + cal(y) << endl;
return 0;
}
形象化的计算,考虑每个点的贡献:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5+5;
int n;
int x[N], y[N];
int main() {
cin >> n;
LL s1 = 0, s2 = 0;
LL res1 = 0, res2 = 0;
for (int i = 0; i < n; i ++ ) cin >> x[i] >> y[i], s1 += x[i], s2 += y[i];
for (int i = 0; i < n; i ++ ) {
res1 += 1ll * (n - 1) * x[i] * x[i] - x[i] * (s1 - x[i]); // 在此可以不用乘2,2x1*x2 本身就重复计算了一次
res2 += 1ll * (n - 1) * y[i] * y[i] - y[i] * (s2 - y[i]);
}
cout << res1 + res2 << endl;
return 0;
}
以上是关于[数学推导] aw3782. 点(推公式+数学推导+数学证明+CF76E)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces1548 D1. Gregor and the Odd Cows (Easy)(皮克公式+gcd+数学推导)