解析
被蓝题虐了。(悲
确实不太难,就是没往那边想。
考虑如果某个值的下标分别位
i
1
,
i
2
,
.
.
.
,
i
n
i_1,i_2,...,i_n
i1,i2,...,in 那么如何计算贡献。
每一个下标和前面统计时作为被减数,和后面统计时作为减数,所以
i
k
i_k
ik 的贡献系数就是
(
k
−
1
)
−
(
n
−
k
)
=
2
k
−
n
−
1
(k-1)-(n-k)=2k-n-1
(k−1)−(n−k)=2k−n−1。
那么所有下标的统计次数其实就是一个公差为 2 的等差数列:
1
−
n
,
3
−
n
,
.
.
.
,
n
−
1
1-n,3-n,...,n-1
1−n,3−n,...,n−1。
那么现在问题就转化成了,有若干个系数,要求重排使得
∑
i
×
a
i
\sum i\times a_i
∑i×ai 最大。
显然应该让系数升序排列,这也必然符合了每一个数提供的系数必然从前往后递增的限制。
方案数就是有相同系数时其可以产生一个全排列的阶乘。
现在还有一个问题是系数加在一起是
1
0
11
10^{11}
1011 级别的,无法直接统计。
利用等差数列的性质,奇偶分别差分即可。
代码
//luogu
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
using namespace std;
const int N=2e6+100;
const int inf=1e9;
const int mod=1e9+7;
inline ll read(){
ll x(0),f(1);char c=getchar();
while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}
while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return x*f;
}
int n,k;
int o=1e6+10;
int sum[N];
ll jc[N];
ll niv2=(mod+1)/2;
inline ll S(ll x,ll y){
return 1ll*(x+y)%mod*(y-x+1)%mod*niv2%mod;
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
n=read();
for(int i=1;i<=n;i++){
int x=read();
sum[1-x+o]++;sum[x-1+o+2]--;
}
jc[0]=1;
for(int i=1;i<=n;i++) jc[i]=jc[i-1]*i%mod;
ll val=0,num=1,cnt=0;
for(int i=2;i<=o+o;i++){
sum[i]+=sum[i-2];
num=num*jc[sum[i]]%mod;
val=(val+S(cnt+1,cnt+sum[i])*((i-o+mod)%mod))%mod;
cnt+=sum[i];
}
printf("%lld %lld\n",val,num);
return 0;
}
/*
*/