1 条题解
-
0
自动搬运
来自洛谷,原作者为

dottle
Cy@?g|^a搬运于
2025-08-24 22:40:07,当前版本为作者最后更新于2022-09-05 18:17:58,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
⚠警告:题解非常摧毁本题的思考体验,作者强烈建议您先思考完题再来看题解
题目简述
对于一个排列,我们维护一个指针 ,初始为 ,每次从 的元素中选一个没删过的删掉,若删掉的比上一个大且 ,则 自增 ,否则结束此过程。你希望使得 ,且会使用最优的策略。
对于所有排列,求可以使得 的概率,对 取模。多次询问,每次给出一个 。
构建映射
首先,明确一点。我们总是会标记比上一次标记的大的最小的那个数,如果没有比就寄了。
为了方便直观理解,我们把 当作大小为 的积木,删掉一个数就把他搭在地上,当我们寄掉的时候,将那些 的还没标记的数按照原排列中的顺序搭起来。最后我们会搭出一个积木塔。
我们考虑 的概率,这一点非常重要。如果你认为后文的积木塔还可能有其他的形态,请再思考一下这句话。后文 性质用到了这一性质。
先来考虑 时我们搭出来的积木塔长啥样:不断增大,在最后一个位置减小 。我们称这个形态为“基本积木塔”。这里如果不保证没取完的话,有可能整个数列都是递增的,就不好办了。

再来考虑 时候长什么样子。我们对于一个例子来分析:对于 ,我们搭出来应该是 。我们还是把塔画出来,然后给塔染色:
- 对于原序列的前 个积木,染上不同的颜色。
- 若我们搭了一个颜色的积木 后,指针新移动到的位置对应的积木也染成 。
- 为每个颜色确定标号,倒数第 个积木的颜色编号为 ,倒数第 个染成 ,以此类推,最后一个积木染色成 。

右边是染色后的结果。蓝色为 ,粉色为 。值得注意的是,因为我们新移动到的数的颜色与我们标记的颜色相同,因此在每个时刻,我们手上每个颜色的数都有恰好一个。
我们染色的目的是展示这样一个事实:
- 一个数列对应的 的塔可以唯一划分为两个 的塔,并为他们确定标号。
- 两个确定好标号的 的塔也能唯一归并出一个已染色的 的塔。归并的方式是,每个塔除去最后一块的部分,按照大小排序;每个塔的最后一块,按照标号排序。
然后,我们再来讨论原数列与已染色的 的塔的对应关系,我们已经介绍了通过数列唯一构造已染色的塔的方法了,我们再来考虑用塔构造数列前 项的方法( 是塔的高度)。
- 根据各个颜色第一个的数,可以求出数列的前 项的集合,对应了 种排列。这个 的系数我们不急着考虑,最后再来乘。
- 取出比上一个放的积木更大的积木中最小的那个,把下一个此颜色的积木放在序列尾,然后更新你手上积木的集合。
其他 个数可以任意排,所以已染色的塔可以对应 个数列。
我们发现这些步骤对于 也成立,那么就很好了。在此,我们再来检视一下我们构建的映射: 个基本积木塔的任何归并都对应一个已染色的积木塔,从而对应 个数列。
开始计数
考虑 个数,将他们搭成基本积木塔的方案数为 ,即选择一个放到最后面。因此基本积木塔的 EGF 为:
则固定 ,积木塔的 EGF 为 。那么我们要求的变为:
$$\sum_{i=m}^{n-1}i![x^i]f^m(x)(n-i)!\binom ni =n!\sum_{i=m}^{n-1}[x^i]f^m(x)=n![x^{n-1}]\frac {f^m(x)}{1-x} $$乘 是因为 EGF,乘 是因为高为 的积木塔对应了 个数列,称组合数是因为我们要从 个数里面选出 个搭塔。
至此,可以一次多项式 exp 解决 的部分分。
上面是搭不成功的概率,那么成功的概率就是:
$$\begin{aligned} &\phantom{={}}1-[x^{n-1}]\frac{f^m}{1-x}\\ &=1-[x^{n-1}]\frac{(e^xx-e^x+1)^m}{1-x}\\ &=1-[x^{n-1}]\sum_i{m\choose i}\frac{(e^x(x-1))^i}{1-x}\\ &=[x^{n-1}]\sum_{i\geq 1}{m\choose i}e^{ix}(x-1)^{i-1}\\ &=[x^{n-1}]\sum_{i\geq 1}{m\choose i}e^{ix}\sum_j{i-1\choose j}x^j(-1)^{i-1-j}\\ &=\sum_{i\geq 1}{m\choose i}\sum_j{i-1\choose j}[x^{n-1-j}]e^{ix}(-1)^{i-1-j}\\ &=\sum_{i\geq 1}{m\choose i}\sum_j{i-1\choose j}\frac{i^{n-1-j}}{(n-1-j)!}(-1)^{i-1-j}\\ \end{aligned} $$至此,可以 预处理后面半截,单次 的询问。结合上文 的部分分可以获得 的高分。
#include<bits/stdc++.h> #define ll long long const int N=20005,mod=998244353; using namespace std; ll gsc(ll x,ll y){ ll ans=1; for(int i=1;i<=y;i<<=1,x=x*x%mod) if(y&i) ans=ans*x%mod; return ans; }int inv(int k){return gsc(k,mod-2);} ll jc[N],ij[N],iv[N]; void init(){ iv[0]=jc[0]=ij[0]=iv[1]=1; for(int i=2;i<N;i++) iv[i]=mod-(mod/i)*iv[mod%i]%mod; for(int i=1;i<N;i++) jc[i]=jc[i-1]*i%mod,ij[i]=ij[i-1]*iv[i]%mod; } int n,q,vis[N],m; ll f[N];int C[N]; int chk(int k){ return k>=mod?k-mod:k; } void solve(){ cin>>n>>q,m=n/2; while(q--){ int x;cin>>x; vis[x]=1; } init(); C[0]=1; for(int i=1;i<=m;i++){ ll pwi=gsc(i,n-1),p=iv[i]; for(int j=0;j<i;j++){ f[i]+=((i+j+1)&1?-1:1)*pwi*C[j]%mod*ij[n-1-j]; f[i]%=mod; pwi=pwi*p%mod; } f[i]=(f[i]%mod+mod)%mod; for(int j=i;j;j--) C[j]=chk(C[j]+C[j-1]); } memset(C,0,sizeof(C)); C[0]=1; for(int i=1;i<=m;i++){ unsigned ll res=0; for(int j=i;j;j--){ C[j]=chk(C[j]+C[j-1]); res+=C[j]*f[j]; res%=mod; } res=res%mod+mod; if(vis[i])cout<<res%mod<<'\n'; } for(int i=m+1;i<=n;i++) if(vis[i])cout<<1<<'\n'; } main(){solve();}设 $g_i=\sum_j{i-1\choose j}\frac{i^{n-1-j}}{(n-1-j)!}(-1)^{i-1-j}$,那么上式便是关于 的卷积。
设 ,则 $g_i=(-1)^{i-1}\sum_j a_{j+1}(i-1)^{\underline j}i^{n-1-j}=\frac{(-1)^{i-1}}{i}\sum_j a_{j}i^{\underline {j}}i^{n-j}$
设 ,则
那么如果我们求出了 ,只需要一个 多 点 求 值 就可以得到 。
考虑分治,设 , 那么答案就为
考虑合并,有 ,
边界为 ,
最后用一次卷积得到每一个 的答案,总时间复杂度 。
- 1
信息
- ID
- 8069
- 时间
- 1800ms
- 内存
- 512MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者