AGC040F Two Pieces 解题报告
AGC040F Two Pieces 解题报告:
题意
数轴上有两个棋子,初始都在 位置,进行 次操作,每次将一个棋子移动一步或者是把靠后的棋子移到靠前的棋子的位置,两个棋子无法区分,求最后两个棋子分别到 的方案数。
。
分析
orz p_b_p_b。
不妨令 为坐标较大的棋子, 为另一个,令 。
把 的坐标和 的坐标作为数对,看作二维平面上的一个点。我们画出直线 ,那么让 走一步就是向右(记为操作 ),让 走一步就是向上(记为操作 ),让 跳到 就是跳到直线上(记为操作 ),且操作 不能碰触直线,最后要到达 。
操作 次数为 的时候很容易处理,可以类似卡特兰数使用折线法。(注意是不能碰触直线,所以要将坐标系整体左移一格)
我们发现跳到直线上很难处理,我们将操作 转化成将直线移到当前位置上。记最后一次操作的坐标为 ,那么我们的终点就应该是 。( 的原因上面说了)
但是还是很难考虑,我们考虑在确定了 以及行走出来的格路之后,将操作 插入操作序列。观察可以得到,对于让直线变为 的操作 ,它的插入位置一定只能是这个直线与格路的最后一个交点(容易发现满足条件的操作 即 ),于是枚举 ,然后插板法计算即可。
复杂度 。
代码
#include<stdio.h>
const int maxn=10000005,mod=998244353;
int n,a,b,ans;
int fac[maxn],nfac[maxn],inv[maxn];
inline int C(int a,int b){
return b==0? 1:((a<b||b<0)? 0:1ll*fac[a]*nfac[b]%mod*nfac[a-b]%mod);
}
int main(){
fac[0]=nfac[0]=1;
for(int i=1;i<maxn;i++)
fac[i]=1ll*fac[i-1]*i%mod,inv[i]=i==1? 1:(mod-1ll*(mod/i)*inv[mod%i]%mod),nfac[i]=1ll*nfac[i-1]*inv[i]%mod;
scanf("%d%d%d",&n,&b,&a);
if(a==0&&b==0){
puts("1");
return 0;
}
for(int i=0;i<=b&&i<a&&i<n-a;i++)//(a-1,i)
ans=(ans+1ll*(C(i+a-1,i)-C(i+a-1,i-1)+mod)*C((n-a-i-1)+(b-i+1)-1,(b-i+1)-1))%mod;
if(a+b==n)
ans=(ans+0ll+C(a+b-1,b)-C(a+b-1,b-1)+mod)%mod;
printf("%d\n",ans);
return 0;
}
标签:
解题报告
, A 数学-K 组合数学
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通