我的思路
首先,如果有两只没喂过球的变色龙,把相同数目的蓝球喂给一只变色龙一定比喂给两只变色龙优(其实就是考虑一下要用多少红球能喂回去)
然后,如果一只变色龙是红的,它可以抵消掉一个蓝球。
于是就得到了一个判断策略:我们钦定一只变色龙,在没有红球出现时吃蓝球。如果有红球,给每只变色龙都喂一个红球。如果这之后还有蓝球,给喂过红球的变色龙喂蓝球。最后的最后如果还剩下球,再喂给那只被钦定的变色龙。你感受一下发现这个是最优的。
这之后我想了些组合数做法,然而全被叉掉了。
看题解8
我发现我自己想的搞法自己都没深入理解,还是思考得不够深入……
题解告诉我们,用\(k\)个球最多能喂出\(x\)只红变色龙的方案数是\(C^{k-1}_{x-1}\),然后我就懵逼了……
然后被\(\color{black}{C}\color{red}{SX}\)教育了一通
大概是这样的:你先把一个球抓出来用来拯救那只被钦定的变色龙。然后根据前面那个策略,最多能喂\(k\)只变色龙的是这种序列:先是一段\(B\),然后一段一段\(RB\)相连的东西(这一段段间只有\(B\))最后一段先是\(B\)后是\(R\)
然后你发现你确定了所有\(RB\)段中\(R\)的位置时,这个序列就已经确定了……吗?
然后如果最后喂给那只被钦定的变色龙的\(B<R\)时,因为最多只能弄出\(x\)只红变色龙,所以你手上的那个球只能是\(B\)。否则你要拯救那只变色龙,你手上的球只能是\(R\)
至此,你就可以通过\(x-1\)个\(R\)的位置确定整个序列,所以方案数就是\(C^{k-1}_{x-1}\)
把所有\(x\geq n\)的方案算一下求个和就行了
代码
#include <bits/stdc++.h> #define N 500005 #define ll long long #define For(i,x,y) for(int i=(x);i<=(y);++i) #define Rof(i,x,y) for(int i=(x);i>=(y);--i) #define Edge(x) for(int i=head[x];i;i=e[i].nxt) #define mset(x,y) memset(x,y,sizeof(x)) #define mod 998244353 using namespace std; int fac[N],invf[N]; int C(int x,int y){ return x>=y?1ll*fac[x]*invf[y]%mod*invf[x-y]%mod:0; } int main(){ int n,k,ans=0; scanf("%d%d",&n,&k); fac[0]=fac[1]=1,invf[0]=invf[1]=1; For(i,2,k){ fac[i]=1ll*fac[i-1]*i%mod; invf[i]=1ll*(1ll*mod-mod/i)*invf[mod%i]%mod; } For(i,2,k) invf[i]=1ll*invf[i-1]*invf[i]%mod; For(i,n,k) (ans+=C(k-1,i-1))%=mod; cout<<ans; }