problem
Description
lahub是一个旅行者的粉丝,他想成为一个真正的旅行者,所以他计划开始一段旅行。lahub想去参观n个目的地(都在一条直道上)。lahub在起点开始他的旅行。第i个目的地和起点的距离为ai千米(ai为非负整数)。不存在两个目的地和起点的距离相同。
从第i个目的地走到第j个目的地所走的路程为 |ai-aj|千米。我们把参观n个目的地的顺序称作一次“旅行”。lahub可以参观他想要参观的任意顺序,但是每个目的地有且只能被参观一次(参观顺序为n的排列)。
lahub把所有可能的“旅行”都写在一张纸上,并且记下每个“旅行”所要走的路程。他对所有“旅行”的路程之和的平均值感兴趣。但是他觉得计算太枯燥了,所以就向你寻求帮助。
Input
第一行一个正整数n。
第二行n个非负整数a1,a2,…,an(1≤ai≤10^7)。
Output
两个整数,答案用最简分数形式输出,第一个为分子,第二个为分母。
Sample Input
3
2 3 5
Sample Output
22 3
【样例提示】
样例有6种可能的旅行:
[2, 3, 5]: 该“旅行”的路程:|2 – 0| + |3 – 2| + |5 – 3| = 5;
[2, 5, 3]: |2 – 0| + |5 – 2| + |3 – 5| = 7;
[3, 2, 5]: |3 – 0| + |2 – 3| + |5 – 2| = 7;
[3, 5, 2]: |3 – 0| + |5 – 3| + |2 – 5| = 8;
[5, 2, 3]: |5 – 0| + |2 – 5| + |3 – 2| = 9;
[5, 3, 2]: |5 – 0| + |3 – 5| + |2 – 3| = 8.
答案为 1 6 × \frac 16× 61×(5+7+7+8+9+8)= 44 6 \frac {44}6 644 = 22 3 \frac {22}3 322
Data Constraint
30% n<=10
50% n<=1000
100% n<=100000
思路
首先将数据从小到大排序,就不用考虑绝对值的问题了。
这道题分为分母和分子两个部分讨论,显然,分母为 n ! n! n!。
如果我们设第0个位置为0,接下来分子又可以分为两种情况:
1 . 0 → a i 0\to a_i 0→ai,可得:
s u m 1 = ∑ a i sum1=\sum a_i sum1=∑ai, t o t 1 = s u m 1 × ( n − 1 ) ! tot1=sum1×(n-1)! tot1=sum1×(n−1)!
2 . a i → a j a_i\to a_j ai→aj,可得:
s u m 2 = 2 × ∑ ( a i − a j ) sum2=2×\sum(a_i-a_j) sum2=2×∑(ai−aj), t o t 2 = s u m 2 × ( n − 1 ) ! tot2=sum2×(n-1)! tot2=sum2×(n−1)!
这些公式的证明过程在这里就不赘述了。
将上述公式合成答案即为: t o t 1 + t o t 2 n ! \frac {tot1+tot2}{n!} n!tot1+tot2
接着:
( n − 1 ) ! × ( s u m 1 + s u m 2 ) n ! \frac {(n-1)!×(sum1+sum2)}{n!} n!(n−1)!×(sum1+sum2)
l a s t : last: last:
s u m 1 + s u m 2 n \frac {sum1+sum2}n nsum1+sum2
公式推来了,但时间复杂度的问题还没有解决。
∑ a i \sum a_i ∑ai求值的时间复杂度是 O ( n ) O(n) O(n)。但 ∑ ( a i − a j ) \sum (a_i-a_j) ∑(ai−aj)复杂度为 O ( n 2 ) O(n^2) O(n2),会TLE。接下来要考虑的就是 ( a i − a j ) (a_i-a_j) (ai−aj)的求值方式。
由于 a i a_i ai只会减 ∑ k = 1 i − 1 a k \sum^{i-1}_{k=1} a_k ∑k=1i−1ak,所以每个 a i a_i ai要减的就是 a i − 1 a_{i-1} ai−1的前缀和,这样就可以在 O ( n ) O(n) O(n)时间内求出。
最后将答案化为最简即可。
Code
#include<cstdio>
#include<iostream>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
#define N 100005
using namespace std;
long long n,a[N],s[N];
long long gcd(long long n,long long m)
{
long long t;
if(n>m) swap(n,m);
while(n!=0)
{
t=m%n;
m=n;
n=t;
}
return m;
}
void qsort(int l,int r)
{
int i=l,j=r,mid=a[(l+r)/2];
while(i<=j)
{
while(a[i]<mid) i++;
while(a[j]>mid) j--;
if(i<=j)
{
long long t;
t=a[i],a[i]=a[j],a[j]=t;
i++,j--;
}
}
if(l<j) qsort(l,j);
if(i<r) qsort(i,r);
}
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
qsort(1,n);
for(int i=1;i<=n;i++)
s[i]=s[i-1]+a[i];
long long s1=0,s2=0;
for(int i=1;i<=n;i++)
s1+=a[i],s2+=2*(a[i]*(i-1)-s[i-1]);
long long s3=s1+s2,gd;
gd=gcd(s3,n);
printf("%lld %lld",s3/gd,n/gd);
}