版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/82940463
传送门
解析:
这不就是一个组合数学的乱搞题吗?
思路:
相信大家应该都做过平面坐标系上,只能向右或向上移动,问到达终点的方案数这种问题。
那么我们试着将这道题转化成上面这个问题。
令我们拥有一个空的队列,我们试着向队列中加入0或1,满足任意时刻1的个数不少于0的个数。若当前队列里面有 个1和 个0,则该队列当前状态对应的平面坐标为 。
那么上面的问题等价于,从 出发,不经过任何 的点 到达 的方案数。
这是一个小学奥数题。。。
我们将坐标系旋转,可以将它看成一个帕斯卡三角形,如果不考虑不能到达的情况,那么从 走到 的方案数就是 。再减去不合法的方案数 就行了。注意特判终点在不合法范围的情况。
代码:
#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;
}