题目链接:传送门
题意:
n个人每个人有n种选择,确定这n个人的排列,使得最后的块数最多。块数是这样算的。1 1 2 算成2块,举一个例子来说明:
1 , 2, 3
然后根据排列来计算块数, 1 1 1 (1块)1 1 2(2块) 1 1 3(两块)1 2 1 (1块)1,2,3(3块) 1 2 2(两块)
下面来分析如何排列与如何计算总的块数。
分析:
构造排列的时候我们首先要想到这个问题,只考虑相邻的两个元素,他们相同的情况就是min(ai,ai+1),因此我们要使相邻的两个元素相差尽可能的大,因此对原来的序列排序,最小,最大,次小,次大。。。
然后再计算的时候我们从反面考虑,不算重复的情况下的块数为a1*a2*...*an,然后减去重复的块数,重复的块数我们只考虑相邻的两个他们有min(ai,ai+1)种,然后我a1*..ai-1*ai+1*..*an种排列可以使他们重复,然后减去就可以了。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define lson num<<1
#define rson num<<1|1
#define gl l,m,lson
#define gr m+1,r,rson
using namespace std;
const int maxn = 1e6+10;
typedef long long LL;
const LL mod = 1e9+7;
LL a[maxn];
LL b[maxn];
LL quick_mod(LL a,LL b){
LL ans = 1;
while(b){
if(b&1) ans = ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
LL n;
scanf("%I64d",&n);
LL ans = 1,fuck;
for(int i=1;i<=n;i++){
scanf("%I64d",a+i);
ans=ans*a[i]%mod;
}
fuck = ans;
sort(a+1,a+n+1);
int cnt = 1;
for(int i=1;i<=n/2+1;i++){
b[cnt++]=a[i];
b[cnt++]=a[n-i+1];
}
ans = ans*n%mod;
for(int i=2;i<=n;i++){
LL tmp = fuck*quick_mod(b[i-1]*b[i]%mod,mod-2)%mod;
ans=(ans-tmp*min(b[i],b[i-1])%mod)%mod;
}
printf("%I64d\n",(ans+mod)%mod);
}
return 0;
}
/****
555
5
1 2 3 4 5
492
***/