CodeForces 340C

来源:互联网 发布:淘宝首页源代码下载 编辑:程序博客网 时间:2024/04/29 14:34

【题意分析】

给定n个点,从原点出发,走遍所有的点(可以不按顺序走)。输出:所有的方案所行走的距离和与总方案数的比(最后的两个数需互质)。

【解题思路】

首先,先不要管数据范围——求总方案数是比较简单的,就是n!,为什么呢?首先,从0到每一个点,有n种方法。然后,剩下了(n-1)个点,因为不可能走回原点,所以还有(n-1)种走法……那么,根据乘法原理,一共有:n*(n-1)*(n-2)*……*1=n!种走法。

然后,我们来看看怎么推导所有方案所行走的距离。

1,          走第一步的时候,一共有n种走法,又因为共有n!种做法,所以,第一步从0~ai(0<i<=n)的走法分别有(n!)/n=(n-1)!种。

2,          下面是第2步到~第n步的走法。像ai~aj这样的走法,并使i,j相邻。除了这两个数以外,其他的排列就有(n-2)!种,那么,这样的i,j一共有(n-1)种走法。所以,一共有(n-2)!*(n-1)=(n-1)!种走法。假如还是不懂的话,看下面的例子:

                 有四个数字:1,2,3,4

  选1,2:有(n-2)!种

  选2,3:有(n-2)!种

……

共(n-1)种。

很明显,一共有(n-2)!*(n-1)=(n-1)!种走法。

因为有ai~aj,所以也可以有aj~ai,所以最终结果要*2。

3,接下来:我们要进行化简。

[(a1+a2+a3+……+an)*(n-1)!+2*(∑|ai-aj|(i!=j))*(n-1)!]/(n!)

=[a1+a2+a3+……+an+2*(∑|ai-aj|(i!=j))]/n

接下来:我们就要考虑计算∑|ai-aj|(i!=j)的问题。

其实,这个就相当于,给定n个点,求所有ai-aj的和。

4,再举一个例子:

 

 

            L1=a2-a1                 L2=a3-a2                      L3=a4-a3

我们记T3为黄色的路线,T2为红色……。T则为∑|ai-aj|(i!=j)。

那么,T=T3+T2+T1

       =(3L3+2L2+1L1)+(2L2+1L1)+(1L1)

       =(1L1)+ (1L1+2L2)+(1L1+2L2+3L3)

很明显,T(i)=T(i-1)+i*Li

那么:可以用变量S把Ti计算出来,再用num把S累加就可以了(注意要乘二)。

如果按照上面的算法,则时间复杂度为O(n)。

5,

Ans = [(a1+a2+a3+……+an)+num]/n

则比为

(a1+a2+a3+……+an)+num:n

最后再用gcd它们的求最大公约数就可以了(记得用longlong)。

【程序】

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=100007;int n;int dis[MAXN];long long sum,ans,s;long long gcd(long long x,long long y){if(!(x%y))return y;return gcd(y,x%y);}int main(){scanf("%d",&n);for(int i=1;i<=n;++i){scanf("%d",&dis[i]);sum+=dis[i];}sort(dis+1,dis+n+1);dis[0]=0;for(int i=1;i<n;++i){s+=(dis[i+1]-dis[i])*i;ans+=(long long)s*2;}long long tgcd=gcd(ans+sum,n);printf("%I64d %I64d\n",(ans+sum)/tgcd,n/tgcd);return 0;}

这是一数学题,很值得思考。


0 0
原创粉丝点击