# CCA的小球

——>点我跳转<——

## 思路

C t o t i × ( n − i ) ! / 2 t o t − i C_{tot}^{i}\times(n-i)!/2^{tot-i}
t o t tot 是一共有多少种颜色有两个球，下同）

a n s = ∑ i = 0 t o t ( ( − 1 ) i × C t o t i × ( n − i ) ! / 2 t o t − i ) ans=\sum\limits_{i=0}^{tot}((-1)^i\times C_{tot}^i\times (n-i)!/2^{tot-i})

## 代码

#include<cstdio>
#include<algorithm>
#define ll long long
#define mo 1000000007

using namespace std;

int n, a[1000001];
int two;
ll ans, two_times[1000001], inv[1000001], fac[1000001], zf = 1;

ll ksm(ll x, ll y) {//用来算逆元的
ll re = 1;
while (y) {
if (y & 1) re = (re * x) % mo;
x = (x * x) % mo;
y >>= 1;
}
return re;
}

void init() {//预处理
two_times[0] = inv[0] = fac[0] = 1;
for (int i = 1; i <= 1000000; i++) two_times[i] = (two_times[i - 1] * 2) % mo;
for (int i = 1; i <= 1000000; i++) fac[i] = (fac[i - 1] * i) % mo;
inv[1000000] = ksm(fac[1000000], mo - 2);
for (int i = 1000000 - 1; i >= 0; i--) inv[i] = (inv[i + 1] * (i + 1)) % mo;
}

int main() {
init();

scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}

sort(a + 1, a + n + 1);

for (int i = 2; i <= n; i++)
if (a[i] == a[i - 1]) {
two++;
}

for (int i = 0; i <= two; i++) {//根据式子容斥
ans = (ans + zf * (fac[two] * inv[i] % mo * inv[two - i] % mo * fac[n - i] % mo * ksm(two_times[two - i], mo - 2)) % mo) % mo;
if (ans < 0) ans += mo;
zf = -zf;
}

printf("%lld", ans);

return 0;
}


01-03 63

01-03 32
03-25 10
04-14 205
01-03 33
01-03 35
03-25 8
03-25 16
03-02 434
05-20
03-30
08-12 177