[题解] [CF886E] Maximum Element
题解
题面
返回错误值的方案数就是总方案数减去返回正确值的方案数
于是我们就只要求返回正确值的方案数了
什么时候会返回正确值?
当 \(n\) 未出现的时候均未返回就会返回正确值
所以我们设 \(f[i]\) 为长度为 \(i\) 的序列还没有返回的方案数
有
\[\displaystyle f[i] = \sum_{j=i-k+1}^{i}f[j - 1]\binom{i-1}{j-1}(i - j)!
\]
意为, 对于最大值 \(i\) , 我们假设他放在 \(j\) 位置上, 因为不能返回, 所以 \(i\) 后面不能有 \(k\) 个数
从 \((i - 1)\) 个数中任取 \(j - 1\) 个数放到前面去摆放, 且不能返回值
另外的 \(i - j\) 个数在 \(j\) 后面可以随便摆, 反正最大值已经确定了
所以就是上面那个式子
把他化一下
\[\displaystyle \begin{aligned}f[i] &= \sum_{j=i-k+1}^{i}f[j - 1]\frac{(i-1)!}{(j-1)!}\\\frac{f[i]}{(i-1)!}&=\sum_{j=i-k+1}^{i}\frac{f[j - 1]}{(j-1)!}\end{aligned}
\]
设 \(g[i] = \frac{f[i]}{i!}\)
所以就变成了
\[\displaystyle g[i]=\frac{\sum_{j=i-k}^{i-1}g[j]}{i}
\]
再看最后的答案如何计算
\[\displaystyle ans = n!-\sum_{i=1}^{n}f[i - 1]\binom{n-1}{i-1}(n-i)!
\]
右边那个 \(\sum\) 分析方式同上
拆一下有
\[\displaystyle \begin{aligned}ans &=n! - \sum_{i=1}^{n}f[i - 1]\frac{(n-1)!}{(i-1)!}\\&=n!-\sum_{i=1}^n(n-1)!\frac{f[i - 1]}{(i-1)!}\\&=n!-\sum_{i=1}^n(n-1)!g[i-1]\\&=(n-1)!(n-\sum_{i=0}^{n-1}g[i])\end{aligned}
\]
递推出 \(g\) 即可
Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
const int N = 1000005;
const int mod = 1000000007;
using namespace std;
int n, k, inv[N], ans, sum[N];
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 main()
{
n = read <int> (), k = read <int> ();
if(n <= k + 1) { puts("0"); return 0; }
sum[0] = 1;
for(int i = (ans = 1); i <= n; i++)
{
if(i == 1) inv[i] = 1;
else inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
ans = 1ll * ans * i % mod;
sum[i] = (sum[i - 1] + 1ll * (sum[i - 1] - (i - k - 1 >= 0 ? sum[i - k - 1] : 0) + mod) % mod * inv[i] % mod) % mod;
}
ans = (ans - 1ll * sum[n - 1] * ans % mod * inv[n] % mod + mod) % mod;
printf("%d\n", ans);
return 0;
}