传送门
解析:
这不就是一个组合数学的乱搞题吗?
思路:
相信大家应该都做过平面坐标系上,只能向右或向上移动,问到达终点的方案数这种问题。
那么我们试着将这道题转化成上面这个问题。
令我们拥有一个空的队列,我们试着向队列中加入0或1,满足任意时刻1的个数不少于0的个数。若当前队列里面有 x x x个1和 y y y个0,则该队列当前状态对应的平面坐标为 ( x , y ) (x,y) (x,y)。
那么上面的问题等价于,从 ( 0 , 0 ) (0,0) (0,0)出发,不经过任何 x < y x<y x<y的点 ( x , y ) (x,y) (x,y)到达 ( n , m ) (n,m) (n,m)的方案数。
这是一个小学奥数题。。。
我们将坐标系旋转,可以将它看成一个帕斯卡三角形,如果不考虑不能到达的情况,那么从 ( 0 , 0 ) (0,0) (0,0)走到 ( x , y ) (x,y) (x,y)的方案数就是 ( x + y x ) \begin{pmatrix}x+y\\ x \end{pmatrix} (x+yx)。再减去不合法的方案数 ( x + y y − 1 ) \begin{pmatrix}x+y\\y-1\end{pmatrix} (x+yy−1)就行了。注意特判终点在不合法范围的情况。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline
ll getint(){
re ll num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
inline void outint(ll a){
static char ch[23];
if(a==0)pc('0');
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
cs ll mod=20100403;
ll fac[2000005],inv[2000005],ifac[2000005];
inline
ll C(int n,int m){
return fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
int n,m;
signed main(){
fac[0]=fac[1]=inv[0]=inv[1]=ifac[0]=ifac[1]=1;
n=getint(),m=getint();
for(int re i=2;i<=m+n;++i)
fac[i]=fac[i-1]*1ll*i%mod,
inv[i]=(mod-mod/i)*inv[mod%i]%mod,
ifac[i]=ifac[i-1]*inv[i]%mod;
if(n<m) outint(0);
else outint( (C(n+m,n) - C(n+m,m-1)+mod)%mod );
return 0;
}