P7322题解
发现直接算某个序列的贡献好像很难。
所以我们考虑去算每种能产生贡献的贡献次数。
什么时候会产生贡献呢?
显然要么是加入的是最大值,要么弹出的是最大值
考虑弹出是 \(\max\)。
产生的方案数:\((n-k)(n-k)!(k-1)!\sum\limits_{m=k}^n \binom {m-1}{k-1}\)。
\(n-k\) 不 \(+1\) 的原因是因为他向后移动了。下面同理。
考虑加入是 \(\max\)。
产生的方案数:\((n-k)(n-k)!(k-1)!\sum\limits_{m=k}^n\binom{m-1}{k-1}\)。
考虑弹出的和加入的都是 $ \max$。
弹出的大于加入的产生的方案数:\((n-k)(n-k-1)!(k-1)!\sum\limits_{m=k+1}^n\binom{m-1}{k}\)。
加入的大于弹出的产生的方案数:\((n-k)(n-k-1)!(k-1)!\sum\limits_{m=k+1}^n \binom {m-1} {k}\)。
答案稍微容斥一下就好了。
这是您会发现您连样例都过不了。
原因是每种情况开始都会产生 \(1\) 个贡献。
将之前加上这个及为答案。
#include<bits/stdc++.h>
#define fep(i,l,r) for(int i=l;i<=r;++i)
#define feb(i,r,l) for(int i=r;i>=l;--i)
#define For(i,u) for(int i=head[u];i;i=e[i].nxt)
#define pr pair<int,int>
#define mpr make_pair
#define LL long long
//#define int long long
using namespace std;
const int N = 5e5+5,mod = 998244353;
int n,k,inv[N],fac[N],ifac[N];
inline int read()
{
int s=0,w=1; char ch=getchar();
while(!(ch<='9'&&ch>='0')) {if(ch=='-') w=-1; ch=getchar();}
while( ch<='9'&&ch>='0') {s=(s<<1)+(s<<3)+ch-'0'; ch=getchar();}
return s*w;
}
inline int Mod(int x) {return x>=mod?x-mod:x;}
inline void init()
{
inv[1]=fac[0]=ifac[0]=1;
fep(i,1,n)
{
if(i^1) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
fac[i]=1ll*fac[i-1]*i%mod;
ifac[i]=1ll*ifac[i-1]*inv[i]%mod;
}
}
inline int C(int x,int y)
{
return 1ll*fac[x]*ifac[y]%mod*ifac[x-y]%mod;
}
inline int query(int x)
{
int ans=0;
fep(i,x+1,n)
{
ans=Mod(ans+C(i-1,x));
}
return ans;
}
signed main()
{
n=read(),k=read();
init();
int ans=Mod(2ll*(n-k)*fac[n-k]%mod*fac[k-1]%mod*query(k-1)%mod-2ll*(n-k)*fac[n-k-1]%mod*fac[k-1]%mod*query(k)%mod);
ans=Mod(ans+fac[n]); ans=Mod(ans+mod);
printf("%d",ans);
return 0;
}

浙公网安备 33010602011771号