【性质分析+神奇搞法】AGC021E Ball Eat Chameleons

我的思路

首先,如果有两只没喂过球的变色龙,把相同数目的蓝球喂给一只变色龙一定比喂给两只变色龙优(其实就是考虑一下要用多少红球能喂回去)

然后,如果一只变色龙是红的,它可以抵消掉一个蓝球。

于是就得到了一个判断策略:我们钦定一只变色龙,在没有红球出现时吃蓝球。如果有红球,给每只变色龙都喂一个红球。如果这之后还有蓝球,给喂过红球的变色龙喂蓝球。最后的最后如果还剩下球,再喂给那只被钦定的变色龙。你感受一下发现这个是最优的。

这之后我想了些组合数做法,然而全被叉掉了。

看题解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;
}

猜你喜欢

转载自www.cnblogs.com/PsychicBoom/p/11779587.html