首页 > 其他 > 详细

【CF886E】Maximum Element

时间:2020-01-15 22:02:45      阅读:58      评论:0      收藏:0      [点我收藏+]

题面

洛谷

题解

\(f_i\)表示\(i\)个数的排列,最大的数填在了最后一个位置,且这个\(\text{fast_max}\)函数尚未返回的方案数。

枚举数\(i-1\)的位置,那么\(i-1\)必然填在区间\([i-k,i-1]\)内,否则函数就会返回。

那么我们有
\[ \begin{aligned} f_i&=\sum_{j=i-k}^{i-1}f_j\times (i-j-1)!\times {j-1 \choose i - 2}\&=\sum_{j=i-k}^{i-1}\frac{(i-2)!}{(j-1)!}f_j \end{aligned} \]
你记一个\(\frac{f_j}{(j-1)!}\)的前缀和就可以\(O(n)\)求出所有\(f\)了。

最后算答案你就枚举最大数所在位置然后和算\(f\)的原理相同,就是
\[ Ans=\sum_{i=1}^nf_i\times {n-1\choose i-1}\times (n-i)! \]

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm> 
using namespace std; 
const int Mod = 1e9 + 7; 
const int MAX_N = 1e6 + 5; 
int fpow(int x, int y) { 
    int res = 1; 
    while (y) { 
        if (y & 1) res = 1ll * res * x % Mod; 
        x = 1ll * x * x % Mod; 
        y >>= 1; 
    } 
    return res; 
} 
int N, K, fac[MAX_N], ifc[MAX_N]; 
int f[MAX_N], s[MAX_N]; 
int main () { 
#ifndef ONLINE_JUDGE 
    freopen("cpp.in", "r", stdin); 
#endif 
    cin >> N >> K; 
    fac[0] = 1; for (int i = 1; i <= N; i++) fac[i] = 1ll * fac[i - 1] * i % Mod; 
    ifc[N] = fpow(fac[N], Mod - 2); 
    for (int i = N - 1; ~i; i--) ifc[i] = 1ll * ifc[i + 1] * (i + 1) % Mod;
    f[1] = s[1] = 1; 
    for (int i = 2; i <= N; i++) { 
        f[i] = 1ll * fac[i - 2] * (s[i - 1] - s[max(0, i - K - 1)] + Mod) % Mod; 
        s[i] = (s[i - 1] + 1ll * f[i] * ifc[i - 1]) % Mod; 
    } 
    int ans = (fac[N] - 1ll * s[N] * fac[N - 1] % Mod + Mod) % Mod; 
    printf("%d\n", ans); 
    return 0; 
} 

【CF886E】Maximum Element

原文:https://www.cnblogs.com/heyujun/p/12198904.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!