球场大佬【NOIP2017提高组A组模拟8.17】

Description

每天下午,古猴都会去打羽毛球。但是古猴实在是太强了,他必须要到一些比较强的场去打。但是每个羽毛球场都有许多的人排着队,每次都只能上四个人,每个人都有自己的能力值,然而这四个人的总能力的高低与否才是古猴是否决定参加这个场的关键。
每四个人的总能力值的定义是:任意选两个与另两个PK,能力值的贡献是较高的一组减去较低的一组。比如能力值为5和7的去PK 6和10的差值,那么用较高的减去较低的就是6+10-5-7=4。然后四个人的总能力值要任意两两之间与其他两个的总贡献。如(a,b,c,d)四个人,那么他们的总能力值就是(a,b)一组与(c,d)一组PK,(a,c)一组与(b,d)一组PK,(a,d)一组与(b,c)一组PK,(b,c)一组与(a,d)一组PK,(b,d)一组与(a,c)一组PK,(c,d)一组与(a,b)一组PK这六项PK差值就是四个人的总能力值。
现在,古猴想知道这个场任意四个人的总能力值的和是多少,但是急着要拿拍,你需要马上告诉他这个场的情况?

Input

第一行一个T,接下来T组数据,每组数据第一行一个n,第二行n个整数a[i]表示每个人的能力值,a[i]∈[0,10^9]。

Output

输出一个整数表示任意四个人的总能力值。最后答案对10^9+7取模。

Sample Input

3
4
1 2 3 3
5
1 2 3 4 5
6
9 18 28 23 12 9

Sample Output

10
76
1176

Data Constraint

对于30%的数据n≤50,T≤5
对于另外20%的数据n≤200,T≤10
对于另外50%的数据n≤2000,T≤100
保证所有的n加起来不超过2000


剖解题目

n个数,每次选4个数,再在其中选2个,然后和高的减和低的为贡献,求总贡献。


解法

部分分就不说了。
首先可以将这n个数每两个数求一个和,化为N=(n-1)*n/2个数。
假设x是a,b组成的,那么凡是一个数y不是a或b里一个数组成的,就会和其进行一次比较。
把N个数排个序,维护一个前缀和。
在对原来的n个数里,每一个N里的数涉及到的数做一个和,统计数量。
然后算即可。


代码

#include
#include
#include
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define down(i,a,b) for(int i=a;i>=b;i--)
#define ll long long

using namespace std;

const int maxn=2005,mo=1e9+7;
ll a[maxn],T,n,now;
ll ans,sum[maxn],num[maxn],tot[maxn*maxn];
struct cy{
    ll x,y;
    ll val;
}f[maxn*maxn];

ll read()
{
    ll x=0; char c;
    for(c=getchar();c<'0'||c>'9';c=getchar());
    for(c;c>='0'&&c<='9';c=getchar()) x=x*10+c-48;
    return x;
}
bool cmp(cy a,cy b)
{
    return a.valint main()
{
//  freopen("T.in","r",stdin);
//  freopen("T.out","w",stdout);
    T=read();
    fo(o,1,T){
        n=read();
        memset(f,0,sizeof(f));
        now=0;
        fo(i,1,n){
            a[i]=read(); num[i]=n-1; sum[i]=0;
            fo(j,1,i-1) {
                f[++now].x=i,f[now].y=j,f[now].val=(a[i]+a[j]);
                sum[f[now].x]=(sum[f[now].x]+f[now].val)%mo;
                sum[f[now].y]=(sum[f[now].y]+f[now].val)%mo;
            }
        }
        sort(f+1,f+1+now,cmp);
        tot[0]=ans=0;
        fo(i,1,now) tot[i]=(tot[i-1]+f[i].val)%mo;
        down(i,now,1){
            ll answer=(f[i].val*(i-1)%mo-tot[i-1]+mo)%mo;
            ll cutt=((f[i].val*num[f[i].x]%mo-sum[f[i].x]+mo)%mo+
                (f[i].val*num[f[i].y]%mo-sum[f[i].y]+mo)%mo)%mo;
            ans=(ans+(answer-cutt+mo)%mo+mo)%mo;
            sum[f[i].x]=((sum[f[i].x]-f[i].val)%mo+mo)%mo;
            sum[f[i].y]=((sum[f[i].y]-f[i].val)%mo+mo)%mo;
            num[f[i].x]--; num[f[i].y]--;
        }
        printf("%lld\n",ans*2%mo);
    }
}

球场大佬【NOIP2017提高组A组模拟8.17】_第1张图片

你可能感兴趣的:(信息技术,数学)