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;
}

posted @ 2022-10-19 20:25  starrylasky  阅读(23)  评论(0)    收藏  举报