P1641 [SCOI2010]生成字符串
题目描述
lxhgww最近接到了一个生成字符串的任务,任务需要他把n个1和m个0组成字符串,但是任务还要求在组成的字符串中,在任意的前k个字符中,1的个数不能少于0的个数。现在lxhgww想要知道满足要求的字符串共有多少个,聪明的程序员们,你们能帮助他吗?
输入格式
输入数据是一行,包括2个数字n和m
输出格式
输出数据是一行,包括1个数字,表示满足要求的字符串数目,这个数可能会很大,只需输出这个数除以20100403的余数
输入输出样例
输入 #1 复制
2 2
输出 #1 复制
2
说明/提示
limitation
每点2秒
对于30%的数据,保证1<=m<=n<=1000
对于100%的数据,保证1<=m<=n<=1000000
费马小定理
费马小定理是数论中的一个定理:假如a是一个整数,p是一个质数,那么a^p-a是p的倍数
如果a不是p的倍数,这个定理也可以写成
若a与p互质,且p是质数时,a(p-1)≡1 ,并且,a-1也是a的逆元
有:
a(p-1)=1=a-1a
a(p-1)=a-1a
a(p-2)=a-1
即:
C(n,m)=( n*(n-1)* … * (n-m+1) ) / ( m! )=( n*(n-1)* … * (n-m+1) ) * (m!)(p-2)
= n! * (m! * (n-m)!)20100403
#include<bits/stdc++.h>
#define MAX_INT ((unsigned)(-1)>>1)
#define MIN_INT (~MAX_INT)
#define pi (4*atan(1.0))
#define ll long long
#define inf 0x3f3f3f3f
#define infmax 0x3f3f3f3f3f3f3f3f
using namespace std;
int read()
{
int c=0;int flag=1;
char s;
while((s=getchar())>'9'||s<'0')if(s=='-')flag=-1;
c=s-'0';
while((s=getchar())<='9'&&s>='0') c=c*10+s-'0';
return c*flag;
}
ll mod=20100403;
ll c(ll m,ll n)
{
ll ans1=1,ans2=1,ans3=1;
for(ll i=m;i>(m-n);i--){
ans1=(ans1*i)%mod;
ans1%=mod;
}
for(ll i=1;i<=n;i++){
ans2=(ans2*i)%mod;
ans2%=mod;
}
ll p=mod-2;
while(p>0){
if(p%2==1) ans3=(ans3*ans2)%mod;
ans2=(ans2*ans2) %mod;
p/=2;
}
return (ans1*ans3)%mod;
}
int main(void)
{
ll a,b;
cin>>a>>b;
cout<<(c(a+b,a)-c(b+a,a+1)+mod)%mod;
return 0;
}