【CodeForces - 340C】Tourist Problem (組合數學)
Iahub is a big fan of tourists. He wants to become a tourist himself, so he planned a trip. There are n destinations on a straight road that Iahub wants to visit. Iahub starts the excursion from kilometer 0. The n destinations are described by a non-negative integers sequence a
Iahub wants to visit each destination only once. Note that, crossing through a destination is not considered visiting, unless Iahub explicitly wants to visit it at that point. Also, after Iahub visits his last destination, he doesn't come back to kilometer 0, as he stops his trip at the last destination.
The distance between destination located at kilometer x and next destination, located at kilometer y, is |x - y| kilometers. We call a "route" an order of visiting the destinations. Iahub can visit destinations in any order he wants, as long as he visits all n destinations and he doesn't visit a destination more than once.
Iahub starts writing out on a paper all possible routes and for each of them, he notes the total distance he would walk. He's interested in the average number of kilometers he would walk by choosing a route. As he got bored of writing out all the routes, he asks you to help him.
Input
The first line contains integer n (2 ≤ n ≤ 105). Next line contains n distinct integers a1, a2, ..., an (1 ≤ ai ≤ 107).
Output
Output two integers — the numerator and denominator of a fraction which is equal to the wanted average number. The fraction must be irreducible.
Examples
Input
3
2 3 5
Output
22 3
Note
Consider 6 possible routes:
- [2, 3, 5]: total distance traveled: |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.
The average travel distance is = = .
思路:
zxz大佬一眼就看出來了,是要求點的貢獻,我想想好像真的是這樣,可是不會啊。只好找了大佬的部落格。
題目思路解法來自:大佬的部落格 文章內容也是在大佬部落格的基礎上,加了一點自己的想法。
假設中的j代表了在一個序列中的第j個位置,設=i,那麼的值,即i就代表在有序陣列a中的位置,就是下標(陣列a是我們輸入元素然後排序的陣列)因此就代表,在一種排列中的第j個位置上的值是a[i]。
所以對於任意一個排列,這個排列的距離公式就是。
然後就是考慮每一個對於結果的貢獻度(陣列a已經升序,接下來討論的情況都是在此基礎上的)
由上面的公式我們可以看出某個元素的貢獻度和他周圍相鄰點的貢獻度是有關係的,比如,如果,那麼這個式子就是,那麼的貢獻度就是,而的貢獻度是。
首先考慮的是第一個點對結果的貢獻度,因此假設=i,就是一組數的排序中a[i]這個元素是放在首位的,那麼影響他的貢獻度的只有第二個元素,剩下的n-2個元素隨意排列,如果,那麼(元素升序排列),這個式子就是,因此的貢獻就是,由於之前有個,貢獻是,所以一加一減,貢獻為0。如果,那麼,其貢獻為,兩次都為加,貢獻為。因為第一種情況貢獻為0,所以我們可以只考慮第二種帶來的貢獻,因為我們假設=i,而要求,因此可以選的值有i-1種,剩下的n-2個位置的排列有(n-2)!種,因此我們可以求得總貢獻為。
接下來是考慮最後一個位置的貢獻度(思路同第一步),假設,考慮的取值,其他n−2個元素隨意排列,如果,那麼對答案貢獻是,否則的話,對答案貢獻是。因此這種情況對答案的貢獻就是兩者之和,即:,(乘法的三項分別為:前一個位置的可能取值,剩下位置的排列組合,自身貢獻度),合併後。
最後是考慮在中間n-2中任何一個位置的貢獻,假設,,考慮和的值,其他n-3個元素隨意排列,如果兩個數一個比大另一個比小。那麼對答案的貢獻度是0,以其中一種可能為例,三個數是,則根據距離公式可得,所以其貢獻為0。如果兩個都比大,那麼對答案貢獻就是,如果都比小,那麼對答案貢獻就是,故這種情況對答案的貢獻就是
求得了在不同位置的貢獻,最後加起來就是的總貢獻。
即。
總共的路徑條數n!種(就是n個數隨機排列形成一個序列的種類數),要求期望,所以要除以n!。
進而能夠求得期望的公式為:
ac程式碼:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<string.h>
#define ll long long
#define ull unsigned long long
#define mod 123456789
using namespace std;
ll a[101000];
int main()
{
ll n;
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);//排序
ll ans=0;
for(int i=1;i<=n;i++)
{
ans+=(4*i-2*n-1)*a[i];
}
ll g=__gcd(ans,n);
cout<<ans/g<<" "<<n/g<<endl;
return 0;
}
以下是別的大佬用別的方法做的:
http://www.cnblogs.com/sineatos/p/3522288.html
https://blog.csdn.net/jeremy1149/article/details/56281920