P7322

好神仙!

\(\color{#5bc9}\text{提醒,本文有大量没有推到过程的式子,所以读者可以自己遮住先推一下}\)

Inscription:

有一个长度为 \(k\) 的窗口,在一个长度为 \(n\) 的序列 \(a\) 上滑动,请问滑动窗口中的数的 \(\min\) 共有多少种值。

Solution:

接下来我们考虑之后什么情况才会让答案 \(+1\)。

既然每次向右移动 \(1\) 的长度,那么只有可能删除的数或者新加入的数是最小值答案才有可能 \(+1\)。

对于最左边的数是窗口滑动之前是窗口最小值,进行一波推式子之后(此处省略一万行),可以发现它对答案的贡献有:

\[s1=\sum^{n-k}_{i = 1}C^{k-1}_{n-i} \times (n-k)! \times (k-1)! \times (n-k)
\]

解释一下:

其中从左往右,求和符合是枚举这个最小值的大小,组合数是令窗口中剩余的 \(k−1\) 个数大于最小值的值的个数。

两个阶乘分别是窗口外面的数任意排列和窗口内部除去最小值外任意排列。

最后一个 \(n−k\) 是计算排列中窗口可以在的位置有 \(n−k\) 个。

同理新加入的数的的贡献就为:

\[s2=\sum^{n-k}_{i = 1} C^{k}_{n-i} \times (n-k-1)! \times k! \times (n-k)
\]

但是未免有左右两边都是最小的情况,所以我们要减去。

所以需要减掉的部分为:

\[s3=\sum^{n-k}_{i = 1}C^{k-1}_{n-i} \times (n - k - 1)! \times (k - 1)! \times (n-k) \times (i-1)
\]

\(i−1\) 是最右边小于最左边的个数。

\(\color{violet} \text{注意:最后还需要加上每个排列都缺少的 1 答案,也就是总答案加上 n!}\)。

但是我不甘于 \(O(n-k)\) 的做法(除了预处理),于是就有了下面的事情。

我们来化简 \(s1,s2,s3\)(化简过程略,读者可以自己遮住先推一下)。

\[s1 = \sum^{n-k}_{i=1} \dfrac{n-k}{(n-k-i+1)!} \times (n-k)! \times (n-i)!
\]
\[s2 = \sum^{n-k}_{i=1} \dfrac{1}{(n-k-i)!} \times (n-k)! \times (n-i)!
\]
\[s3 = \sum^{n-k}_{i=1} \dfrac{i-1}{(n-k-i+1)!} \times (n-k)! \times (n-i)!
\]

然后呢,就有一个规律,那就是 \(s1 - s3 = s2\)。

所以答案从 \(s1 + s2 - s3 + n!\) 变成了 \(2 \times s2 + n!\)。

但是,我们还不满足。

\(s2\) 仍然可以化简(读者可以自己遮住先推一下)。

\[s2 = \dfrac{(n+1)!}{k+1} - n!
\]

所以把上面这个式子带入求答案的式子。

所以:

\[\dfrac{2 \times (n+1)!}{k+1} - n!
\]

所以完结撒花!!

最后贴上代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 998244353;
int qpow(int a,int b)
{
int res = 1;
while(b)
{
if(b & 1)
{
res = res * a % mod;
}
b >>= 1;
a = a * a % mod;
}
return res;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n,k;
cin >> n >> k;
int fac = 1;
for(int i = 1;i <= n;i++)
{
fac = fac * i % mod;
}
cout << (2 * (fac * (n + 1) % mod) * qpow(k + 1,mod - 2) % mod - fac + mod) % mod;
return 0;
}

随机推荐

  1. JVM简明笔记3:类加载机制

    1 类的加载 类的加载指的是将类的 .class 文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class 对象,用来封装类在方法区内的数据结 ...

  2. 力扣121(java&python)-买卖股票的最佳时机(简单)

    题目: 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格. 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票.设计一 ...

  3. 力扣429(java)-构造矩形(简单)

    题目: 作为一位web开发者, 懂得怎样去规划一个页面的尺寸是很重要的. 所以,现给定一个具体的矩形页面面积,你的任务是设计一个长度为 L 和宽度为 W 且满足以下要求的矩形的页面.要求: 你设计的矩 ...

  4. Apsara Stack 技术百科 | 如何「场景化」的企业上云

    简介: 企业上云离不开数据和业务上云,如何在确保安全的前提下,低成本高效率的平滑上云,在云上又能真正解决哪些实际业务问题?混合云君今天给大家讲讲最经典的三个场景~ 随着"十四五"规 ...

  5. 消息队列Kafka「检索组件」重磅上线!

    ​简介:本文对消息队列 Kafka「检索组件」进行详细介绍,首先通过对消息队列使用过程中的痛点问题进行介绍,然后针对痛点问题提出相应的解决办法,并对关键技术技术进行解读,旨在帮助大家对消息队列 Kaf ...

  6. 阿里云张献涛:自主最强DPU神龙的秘诀

    ​简介:读懂云计算,才能看清DPU热潮. 微信公众号搜索"弹性计算百晓生",获取更多云计算知识. 如果细数最近火爆的科技概念,DPU必然位列其中. 这是英伟达一手捧红的新造富故事, ...

  7. rerank来提升RAG的准确度的策略

    RAG(Retrieval-Augmented Generation)是一种结合检索和生成两种技术的模型,旨在通过检索大规模知识库来增强文本生成任务的准确性. 要通过reranking(重排序)来提升 ...

  8. [GPT] golang 有那么多系统包 该如何了解和学习

    在学习和了解Golang(Go语言)的系统包时,可以遵循以下步骤来逐步熟悉并掌握它们: 1. 官方文档阅读: 首先从官方文档入手,Go的标准库文档非常详尽且易于理解.你可以访问 Go标准库 来查看各个 ...

  9. 使用 DISM 安全清理 C 盘 WinSxS 文件夹空间

    本文将介绍如何使用系统内置 DISM 工具进行安全清理 C 盘空间,清理 WinSxS 文件夹里面的可回收删除的程序包空间 开始之前,先使用管理员权限打开 CMD 或 PowerShell 命令行窗口 ...

  10. 通过Ingress-nginx实现灰度发布---灰度发布(22)

    1.通过Ingress-nginx实现灰度发布 场景一: 将新版本灰度给部分用户 假设线上运行了一套对外提供 7 层服务的 Service A 服务,后来开发了个新版本 Service A' 想 要上 ...