题意
一个序列是好的序列,满足可以通过下面的操作使得这个序列的所有元素都相等。
操作:选择序列中的两个下标i,j,在选择一个x(0 < x <= ai),ai - x,aj + x,这个操作有一个代价为|i - j| * x,且每次操作之后在之后的操作中,不能给ai执行增加x的操作,不能给aj执行减去x的操作。
一个平衡的序列是指把一个序列变为好的序列的最小代价和最大代价相等。
输入
输入一个n表示序列长度,下面一行输入n个数表示这个序列。
输出
可以对这个序列重新排序,询问最后有多少序列个是满足平衡序列(两个序列不相等满足至少有一个下标的值不同)。
思路
首先,对一个数 + x,一个数 - x。所有数的总和是不变的,所有最后生成的好的序列是唯一的,等于∑ai / n。
造成一个序列值不相同情况为
所以为避免这种情况,比平均值大的和比平均值小的应该分别放在两边。和平均值相等的可以放在任意位置,因为他可以起传递作用,并不影响两个值直接的变化。
之后就变成组合数学中的问题:
1.计算比平均值大和比平均值小的排列方案数,也就等价于计算多重集的排列数。 S!/(s1! * s2! *…sk!)S为总个数,si它的一种子元素的个数一共有k种。
2.两个可以一前一后有两种方案(特殊当他两的数目一个值为1时可以任意排列,即不存在图片中的情况)
3.等于平均值的数可以任意排列,可以等价于有n个坑,k个完全相同的箱子可以放在坑里,一个坑内是没有个数限制的,有多少种方案。是一个多重集的排列问题,可以使用隔板法解决,答案为C(n + k - 1,n - 1).
答案为这些之积、
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10,mod = 1e9 + 7;
map<int ,int > mp;
int a[N];
int fact[N],infact[N];
int qmi(int a,int b){
int res = 1;
while(b){
if(b & 1) res = 1ll * res * a % mod;
a = 1ll * a * a % mod;
b >>= 1;
}
return res;
}
void init(){
fact[0] = infact[0] = 1;
for(int i = 1;i < N;i++){
fact[i] = 1ll * fact[i - 1] * i % mod;
infact[i] = 1ll * infact[i - 1] * qmi(i,mod - 2) % mod;
}
}
int C(int a,int b){
if(a < b) return 0;
return 1ll * fact[a] * infact[b] % mod * infact[a - b] % mod;
}
int main(){
init();
int lans = 1,rans = 1;
int ans = 1;
ll sum = 0;
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++){
int x;
scanf("%d",&x);
mp[x]++;
sum += x;
}
int p = sum / n;
if(sum % n){
puts("0");
return 0;
}
int lcnt = 0,rcnt = 0;
for(auto item:mp){
int x = item.first;
int cnt = item.second;
// cout << x << ' ' << cnt <<endl;
if(x < p) lans = 1ll * lans * infact[cnt] % mod,lcnt += cnt;
else if(x > p) rans = 1ll * rans * infact[cnt] % mod,rcnt += cnt;
}
lans = 1ll * lans * fact[lcnt] % mod;
rans = 1ll * rans * fact[rcnt] % mod;
int cnt = lcnt + rcnt + 1;
int k = mp[p];
ans = 1ll * lans * rans % mod ;
// cout << ans << endl;
if(lcnt == 1) ans = 1ll * ans * (rcnt + 1) % mod;
else if(rcnt == 1) ans = 1ll * ans * (lcnt + 1) % mod;
else if(lcnt && rcnt)ans = 1ll * ans * 2 % mod;
// cout << ans << endl;
ans = 1ll * C(cnt + k - 1,cnt - 1) * ans % mod;
cout << ans << endl;
return 0;
}