[luoguP9823] The Journey of Geor Autumn

题意

给定 \(n,k\),求满足

\[\forall i > k, p_i > \min_{j=n-k}^{n-1} p_j \]

的排列 \(p\) 的数量。

sol

首先考虑 \(1\),容易发现,当 \(1\) 位于 \(p_k\) 之后时,永远无法满足条件,因此必须要放到 \(k\) 的左侧,而当放置了 \(1\) 以后,右侧最小的数又会成为新的 "\(1\)",因此会变为新的子任务。假设 \(1\) 被放在了 \(x\) 的位置,那么左侧方案数即为 \(A_{n-1}^{x-1}=\dfrac{(n-1)!}{(n-x)!}\),设 \(f_i\) 表示长度为 \(i\) 的子任务,则

\[f_i=\sum_{j=1}^{\min\{i, k\}}\dfrac{(i-1)!\cdot f_{i-j}}{(i-j)!}=(i-1)!\sum_{j=1}^{\min\{i, k\}}\dfrac{f_{i-j}}{(i-j)!} \]

前缀和优化即可

代码

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;
typedef long long LL;

const int N = 10000005, mod = 998244353;

int f[N], factor[N], inv[N];
int n, k;
int sum[N];

int qpow(int a, int k, int p){
    int ans = 1;
    while (k) {
        if (k & 1) ans = (LL) ans * a % p;
        a = (LL) a * a % p;
        k >>= 1;
    }
    return ans;
}

int main(){
    scanf("%d%d", &n, &k);
    factor[0] = 1, sum[0] = 1;
    for (int i = 1; i <= n; i ++ ) factor[i] = (LL) factor[i - 1] * i % mod;
    inv[n] = qpow(factor[n], mod - 2, mod);
    for (int i = n - 1; i >= 0; i -- ) inv[i] = (LL) inv[i + 1] * (i + 1) % mod;
    for (int i = 1; i <= n; i ++ ){
        f[i] = (f[i] + (LL) factor[i - 1] * ((sum[i - 1] - ((i - k - 1) < 0 ? 0 : sum[i - k - 1])) % mod + mod) % mod) % mod;
        sum[i] = (sum[i - 1] + (LL) f[i] * inv[i] % mod) % mod;
    }
    printf("%d\n", f[n]);
}
posted @ 2025-02-07 19:47  是一只小蒟蒻呀  阅读(18)  评论(0)    收藏  举报