ATG21E Ball Eat Chameleons 学习笔记

ATG21E Ball Eat Chameleons 学习笔记

Luogu Link

题意简述

\(n\) 只蓝色变色龙。现在你有 \(k\) 个红或蓝的球,每次你指定一只变色龙吃下你给的球。

一只变色龙从蓝变红当且仅当它吃的红球比蓝球多,从红变蓝当且仅当它吃的蓝球比红球多。

问有多少种给球的颜色序列可以使得存在喂球的方案让所有变色龙在最后都是红的。

\(n,k\le 5\times 10^5\)

做法解析

对于前人(clz)之述备矣的这一段我就直接摘抄了。

既然是对球的颜色序列计数,那么就只需要考虑,对于每一个颜色序列,判断它是否可行。

假设总共喂了 \(R\) 个红球和 \(B\) 个蓝球,满足 \(R+B=K\)

首先考虑一只变色龙在什么情况下最终才会变成红色:

  1. 它吃的红球比蓝球多。
  2. 它吃的红球和蓝球一样多(且不为 \(0\) 个),但是吃的最后一个球是蓝球。

如果 \(R<B\),也就是红球总数比蓝球少,那么显然无解。

如果 \(R\ge B+N\),也就是红球比蓝球还多 \(N\) 个,可以直接让每只变色龙吃的红球都比蓝球多,一定有解。

否则 \(B\le R<B+N\),就只能让一些变色龙吃的红球和蓝球一样多,另一些变色龙红球吃的更多一些。

可以枚举每个 \(R\)。这样,\(R<B\) 的部分直接跳过,\(R\ge B+N\) 你瞎鸣肥怎么排都行。

\(B\le R<B+N\) 意味着,(因为红球数量紧张,我们规定每个变色龙吃的红球最多比蓝球多 \(1\),在这种前提下),我们有 \(R-B\) 只变色龙吃的红球比蓝球多 \(1\),剩下的 \(N-(R-B)\) 只吃的红蓝球数相等且最后吃的是蓝球。后面半句实际上等价于能找出 \(N-(R-B)\) 对(互相独立的)形如 \(\texttt{R,B}\) 的子序列。

进一步转化,值得学习的一步来了:我们将红视为加一蓝视为减一,那么最后不属于 \(\texttt{R,B}\) 的蓝的数量即为折线最低点(即为值最小的前缀),上文条件等价于最小前缀的绝对值不大于 \(B-(N-(R-B))=R-N\)。碰到这种若干由两个字码组成的简单模式需要一定数量的时候,你可以考虑用折线将其可视化一下。

pVl1nit.md.png

你再看两眼这玩意,你会发现实际上这还是类似于卡特兰数走格子那一套的计数。

额为了看着舒服点我们再把这玩意翻转一下,变成算“向右走为红,向上走为蓝,最后要走到 \((R,B)\) 且不能逾越 \(y=x+R-N\) 的方案数”。答案即为 \(\binom{R+B}{R}-\binom{R+B}{2R-N+1}\)。这里整个问题已经转化为LGP1641了。

代码实现

#include <bits/stdc++.h>
using namespace std;
using namespace obasic;
using namespace omodint;
using mint=m998;
const int MaxN=5e5+5;
mint facr[MaxN],finv[MaxN];
using namespace omathe;
int N,K;mint ans;
int main(){
    readis(N,K);premwork(K);
    if(K<N){writi(0);return 0;}
    for(int cr=N,cb=K-cr;cr<=K;cr++,cb--){
        if(cr>=cb+N){ans+=Comb(K,cr);continue;}
        ans+=Comb(cr+cb,cr)-Comb(cr+cb,2*cr-N+1);
    }
    writil(miti(ans));
    return 0;
}
posted @ 2025-07-12 11:12  矞龙OrinLoong  阅读(10)  评论(0)    收藏  举报