难度:思维题
算法:逆元+组合数学
题解:
图片来源:www.cnblogs.com/Y-E-T-I/p/7384430.html
我们设选1为(1,1),选0为(1,-1)
目标是(n+m,n-m)
总方案数为,因为有n+m个位置,放n个1
然后要减去不合法的,即通过y=-1的。将线路与y=-1交点的左边沿着y=-1做对称操作,则最后等价于从(0,-2)走到(n+m,n-m)的方案数
所以向上走n-m+2则有
所以不合法方案为C(n+m,n+1)
ans=C(n+m,n)-C(n+m,n+1)
我用的是线性筛逆元,求解。
注意:最后要(......%mod+mod)%mod!!!
代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#define ll long long
#define N 2000005
using namespace std;
const ll p=20100403;
ll inv[N<<1];//一定要开long long
void invv()
{
inv[0]=1;
inv[1]=1;
for(int i = 2;i <= N;i++)
{
inv[i]=(p-p/i)*inv[p%i]%p;
}
}
ll jc[N];
ll ans1,ans2;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
invv();
for (int i = 2;i <= n+m;i++)
{
inv[i]=(inv[i]*inv[i-1])%p;
}
jc[1]=1;
for(int i = 2;i <= n+m;i++)
{
jc[i]=(jc[i-1]*i)%p;
}
ans1=((jc[n+m]*inv[n])%p*inv[m])%p;
ans2=((jc[n+m]*inv[n+1])%p*inv[m-1])%p;
printf("%lld\n",(ans1-ans2+p)%p);
return 0 ;
}