CF1096E 题解

题目链接

题目大意

小明在打比赛,包括小明自己一共有 \(p\) 名选手参赛,每个人的得分是一个非负整数。最后的冠军是得分最高的人,如果得分最高的人有多个,就等概率从这些人中选一个当冠军。
现在小明已知了自己的得分大于等于 \(r\),所有选手的得分和为 \(s\)。求小明获胜的概率,结果对 \(998244353\) 取模。

\(Solution:\)

我们只需要保证小明为\(TopScorer\)即可,即保证剩下的人的分数都\(\leq\)小明的分数,\(ans\)即为小明为\(TopScorer\)的方案数除以总方案数

因为这是DP专题里面的题,我们令\(f_{s,p,m}\)表示\(p\)名选手总得分为\(s\),每名选手分数不超过\(m\)的方案数,显然有:

\(f_{s,p,m}=\sum\limits_{i=0}^{m}{f_{s-i,p-1,m}}\),可以维护一个前缀和,但是这是\(O(srp)\)的,显然\(TLE\)

但是这启发我们我们可以考虑单独计算某个\(dp\)值(答案用到的\(dp\)状态不多)为什么我就没有被启发到

那么\(f_{s,p,m}=\sum\limits_{i=0}^{p}{(-1)^{i} \times C_p^i \times C_{s+p-1-i(m+1)}^{p-1}}\)

问题来了,如何理解这个式子?(天知道我为了理解它花了多长时间)

第一种理解方式:容斥

遇到有关最大值的问题,可以转化为“不超过”

在此题中,即为其他人的分数都不超过小明的分数

即计算所有情况-至少一个人超过\(m+\)至少两个人超过\(m-\)至少三个人超过\(m\)\(+...\)(奇加偶减),所以容斥系数即为\((-1)^i\)

再考虑\(C_p^i \times C_{s+p-1-i(m+1)}^{p-1}\),首先在\(p\)个人中选出\(i\)个人,即为\(C_p^i\),再给每个人分配\((m+1)\)的分数(意思即保证这些人的分数都大于\(m\)),然后就是允许有空盒子的隔板法了

第二种理解方式:二项式反演

二项式反演就是这样的很对称一个式子:

\(f_{n}=\sum_{i=0}^{n}(-1)^{i} \times C_{n}^{i} \times g_{i} \Longleftrightarrow g_{n}=\sum_{i=0}^{n}(-1)^{i} \times C_{n}^{i} \times f_{i}\)

一个很对称的常见表达为:\(f_{n}=\sum_{i=0}^{n} C_{n}^{i} \times g_{i} \Longleftrightarrow g_{n}=\sum_{i=0}^{n}(-1)^{n-i} \times C_{n}^{i} \times f_{i}\)

具体证明可以看看这篇博客

那么我们把它套到我们的式子中,设\(A(x)\)表示\(\leq x\)个人不超过\(m\)的方案数,\(B(x)\)表示恰好有\(x\)个人不超过\(m\)的方案数,显然有:

\(A(n)=\sum\limits_{i=0}^nC_n^i \times B(i)\),由二项式反演:

\(B(n)=\sum\limits_{i=0}^{n}{(-1)^{n-i} \times C_n^i \times A(i)}\),将 \(i\) 全部换成 \(n-i\)(这么换相当于把原来的正序\(\sum\)改成了倒序,不会影响答案),有:

\(B(n)=\sum\limits_{i=0}^{n}{(-1)^{i} \times C_n^i \times A(n-i)}\),(其中 \(C_{n}^{n-i}=C_{n}^i\),所以不变)因为有\(n-i\)个人不超过\(m\) \(\Longleftrightarrow\)\(i\)个人超过\(m\),那么给每个人分配\(m+1\)分,再使用隔板法,有:

\(B(p)=\sum\limits_{i=0}^{p}{(-1)^i \times C_p^i \times C_{s+p-1-i(m+1)}^{p-1}}\),这样就得到了同样的结论

回归正题,我们得到了\(f_{s,p,m}\)的表达式后,我们尝试用它来表示\(answer\),那么:

\[ans=\frac{\sum_{t=r}^{s} \sum_{q=1}^{p}\left(\begin{array}{c} p-1 \\ q-1 \end{array}\right) \times \frac{1}{q} \times f_{s-q t, p-q, t-1}}{\left(\begin{array}{c} s-r+p-1 \\ p-1 \end{array}\right)}\]

问题又双叒叕来了,如何解释这个式子?

外层循环\(t\)枚举的是小明的分数,即所有人的分数\(\leq t\)
\(q\)枚举的是有多少同分的最高分,\(C_{p-1}^{q-1}\) 描述的是从\(p-1\)个人(\(-1\)意即除去小明)中选出 \(q-1\)个人,\(\frac{1}{q}\)即题目中同分的人均分成为\(TopScorer\)的概率;
\(f_{s-qt, p-q, t-1}\)描述的是除去最高分的人,剩下的方案数;
最后分母 \(C_{s-r+p-1}^{p-1}\) 描述的是总的方案数。

呼~终于讲完了,上代码

\(Code:\)

#include<bits/stdc++.h>
using namespace std;
namespace my_std
{
	typedef long long ll;
	typedef double db;
	#define pf printf
	#define pc putchar
	#define fr(i,x,y) for(register ll i=(x);i<=(y);i++)
	#define pfr(i,x,y) for(register ll i=(x);i>=(y);i--)
	#define go(x) for(ll i=head[u];i;i=e[i].nxt)
	#define enter pc('\n')
	#define space pc(' ')
	#define fir first
	#define sec second
	#define MP make_pair
	const ll inf=0x3f3f3f3f;
	const ll inff=1e15;
	inline ll read()
	{
		ll sum=0,f=1;
		char ch=0;
		while(!isdigit(ch))
		{
			if(ch=='-') f=-1;
			ch=getchar();
		}
		while(isdigit(ch))
		{
			sum=(sum<<1)+(sum<<3)+(ch^48);
			ch=getchar();
		}
		return sum*f;
	}
	inline void write(ll x)
	{
		if(x<0)
		{
			x=-x;
			pc('-');
		}
		if(x>9) write(x/10);
		pc(x%10+'0');
	}
	inline void writeln(ll x)
	{
		write(x);
		enter;
	}
	inline void writesp(ll x)
	{
		write(x);
		space;
	}
}
using namespace my_std;
const ll N=5500,mod=998244353;
ll p,r,s,mul[N],inv[N],c[N][N],ans;
inline ll ksmod(ll a,ll b)
{
	ll ans=1;
	while(b)
	{
		if(b&1)
		{
			ans=(ans*a)%mod;
		}
		a=(a*a)%mod;
		b>>=1;
	}
	return ans;
}
inline ll C(ll n,ll m)
{
	if(m>n||m<0||n<0) return 0;
    ll res=inv[m]*inv[n-m]%mod;
    res=res*mul[n]%mod;
    return res;
}
inline void init()
{
	mul[0]=inv[0]=1;
    for(ll i=1;i<=p+s;i++) mul[i]=(mul[i-1]*i)%mod;
    inv[p+s]=ksmod(mul[p+s],mod-2);
    for(ll i=p+s-1;i;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
inline ll f(ll s,ll p,ll m)
{
	if(s==0&&p==0) return 1;
	ll ans=0,tmp=1;
	fr(i,0,p)
	{
		if(s+p-1-i*(m+1)<0) break; 
		ans=(ans+tmp*C(p,i)%mod*C(s+p-1-i*(m+1),p-1)%mod+mod)%mod;
		tmp*=-1; 
	}
	return ans;
}
int main(void)
{
	p=read(),s=read(),r=read();
	init();
	fr(t,r,s) fr(q,1,p) ans=(ans+(C(p-1,q-1)*ksmod(q,mod-2))%mod*f(s-q*t,p-q,t-1))%mod;
	ans=(ans*ksmod(C(s-r+p-1,p-1),mod-2))%mod;
	writeln(ans); 
	return 0;
}

所以这道题正解和dp有什么关系?

完结撒花!!!

posted @ 2020-04-02 14:12  L_G_J  阅读(166)  评论(1编辑  收藏  举报