[题解] [CF938E] Max History
Posted ztlztl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解] [CF938E] Max History相关的知识,希望对你有一定的参考价值。
题面
题解
考虑计算每一个数的贡献
我们设严格小于第 (i) 个数的数共有 (m_i) 个
只要这个数前面的数都比他小并且后面有比他大的数他的贡献就能算进去
那么对于这个数 (i) 的贡献就是
[
displaystyle a_i(n-m_i-1)!(m_i)!inom{n}{n-m_i}
]
代表我们随意拜访比 (i) 大的数, 保证放在 (i) 后面即可
然后把这些数加上 (i) 自己插入 (n) 个位置中, 剩下的位置放这 (m_i) 个数
然后这 (m_i) 个数也可以自由排列, 对答案没有影响
所有的数的贡献加起来就行
最大值无法贡献
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
const int N = 1000005;
const int mod = 1000000007;
using namespace std;
int n, a[N], m[N], cnt, last, fac[N], inv[N], ans;
template < typename T >
inline T read()
{
T x = 0, w = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * w;
}
int C(int n, int m)
{
return 1ll * fac[n] * inv[n - m] % mod * inv[m] % mod;
}
int fpow(int x, int y)
{
int res = 1;
for( ; y; y >>= 1, x = 1ll * x * x % mod)
if(y & 1) res = 1ll * res * x % mod;
return res;
}
int main()
{
n = read <int> ();
for(int i = 1; i <= n; i++)
a[i] = read <int> ();
sort(a + 1, a + n + 1);
last = 1;
for(int i = 2; i <= n + 1; i++)
if(a[i] != a[last])
{
m[i] = i - 1;
last = i;
}
else m[i] = m[i - 1];
for(int i = (fac[0] = 1); i <= n; i++)
fac[i] = 1ll * fac[i - 1] * i % mod;
inv[n] = fpow(fac[n], mod - 2);
for(int i = n - 1; i >= 0; i--)
inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
for(int i = 1; i <= n; i++)
{
if(m[i] == m[n]) break;
ans = (ans + 1ll * a[i] * C(n, n - m[i]) % mod * fac[m[i]] % mod * fac[n - m[i] - 1] % mod) % mod;
}
printf("%d
", ans);
return 0;
}
以上是关于[题解] [CF938E] Max History的主要内容,如果未能解决你的问题,请参考以下文章