旅行者

前言
“少小离家老大回,安能辨我是雄雌。 ”今天,嘟嘟老师讲一道看上去难实际很简单的题——旅行者。
题目描述
Smart是一个旅行者的粉丝,他想成为一个真正的旅行者,所以他计划开始一段旅行。Smart想去参观n个目的地(都在一条直道上)。Smart在起点开始他的旅行。第i个目的地和起点的距离为a[i]千米(a[i]为非负整数)。不存在两个目的地和起点的距离相同。
从第i个目的地走到第j个目的地所走的路程为 |a[i]-a[j]|千米。我们把参观n个目的地的顺序称作一次“旅行”。Smart可以参观他想要参观的任意顺序,但是每个目的地有且只能被参观一次(参观顺序为n的排列)。
Smart把所有可能的“旅行”都写在一张纸上,并且记下每个“旅行”所要走的路程。他对所有“旅行”的路程之和的平均值感兴趣。但是他觉得计算太枯燥了,所以就向你寻求帮助。
输入
第一行一个正整数n。
第二行n个非负整数a[1],a[2],….,a[n](1≤a[i]≤10^7)。
输出
两个整数,答案用最简分数形式输出,第一个为分子,第二个为分母。
样例输入
2 3 5
样例输出
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 *(5+7+7+8+9+8)=44/6=22/3。
数据范围限制
30%的数据:n≤10;
50%的数据: n≤1000;
100%的数据:n≤100000。
思路
此题很多人尝试去枚举,不过后来是怎么也暴力不出来的。这时候,就只能循环一步一步推。首先来个快排,然后算出a[1]…a[n]之间的和(暂用ans表示),之后循环,每个点的找一遍,ans:=ans+(n-i*2+1)*a[i]*2;之后算出他们的最大公因数,约分后输出最简分数就行了。
代码

var
        a:array[1..100000] of int64;
        i,n:longint;
        ans:int64;
procedure sb(l,r:longint);
var
        i,j:longint;
        k,p:int64;
begin
        i:=l;
        j:=r;
        k:=a[(l+r) div 2];
        while (i<j) do
        begin
                 while (a[i]>k) and (i<r) do inc(i);
                 while (a[j]<k) and (l<j) do dec(j);
                 if (i<=j) then
                 begin
                        p:=a[i];
                        a[i]:=a[j];
                        a[j]:=p;
                        inc(i);
                        dec(j);
                 end;
        end;
        if (i<r) then sb(i,r);
        if (l<j) then sb(l,j);
end;
function lsb(x,y:int64):int64;
var
        z:int64;
begin
        repeat
                z:=x mod y;
                x:=y;
                y:=z;
        until z=0;
        lsb:=x;
end;
begin
        readln(n);
        for i:=1 to n do
        begin
                read(a[i]);
                inc(ans,a[i]);
        end;
        sb(1,n);
        for i:=1 to n do
                ans:=ans+(n-i*2+1)*a[i]*2;
        write(ans div lsb(ans,n),' ',n div lsb(ans,n));
end.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值