加成原理
很简单的一个题,为啥要放后面?
首先,显然,答案只跟每一种长度的链有多少个有关。
最长的链是从根开始的,因此最长的链只有一个,我们特判掉。
对于一个长度为
从次长链向短链依次枚举,对于一个新来的链,看到底能放在多少个节点下,容易发现,只有下面的链长大于等于新来的链长的才能插入这个新链,想要维护这个,因为点数有限,就可以瞎搞了,我喜欢树状数组,因此下面的代码中使用树状数组。然后我们就做完了。
代码:
#include <bits/stdc++.h>
#define int long long
#define lowbit(x) ((x)&-(x))
#define mod 20051131
#define MAXN 10000005
using namespace std;
int n, k, t[MAXN], f[MAXN], ans;
map<int, int> mp;
vector<int> vec;
void update(int x) {
while (x <= n) {
t[x]++;
x += lowbit(x);
}
}
int query(int x) {
int ans = 0;
while (x) {
ans += t[x];
x ^= lowbit(x);
}
return ans;
}
signed main() {
f[0] = 1;
for (int i = 1; i <= 1000000; i++) {
f[i] = f[i - 1] * i % mod;
}
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> k;
mp[k]++;
}
for (pair<int, int> i : mp) {
vec.push_back(i.second);
}
sort(vec.begin(), vec.end());
reverse(vec.begin(), vec.end());
for (int i : vec) {
if (ans == 0) {
ans = f[i - 1];
for (int j = 1; j <= i; j++) {
update(j);
}
continue;
}
ans *= f[i - 1];
ans %= mod;
ans *= query(n) - query(i);
ans %= mod;
for (int j = 1; j <= i; j++) {
update(j);
}
}
cout << ans << endl;
return 0;
}