String
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2552 Accepted Submission(s): 755
Problem Description
Recently,
lxhgww received a task : to generate strings contain ‘0‘s and ‘1‘s
only, in which ‘0‘ appears exactly m times, ‘1‘ appears exactly n times.
Also, any prefix string of it must satisfy the situation that the
number of 1‘s can not be smaller than the number of 0‘s . But he can‘t
calculate the number of satisfied strings. Can you help him?
Input
T(T<=100) in the first line is the case number.
Each case contains two numbers n and m( 1 <= m <= n <= 1000000 ).
Output
Output the number of satisfied strings % 20100501.
Sample Input
1
2 2
Sample Output
2
Author
lxhgww
Source
HDOJ Monthly Contest – 2010.05.01
题意:
0,1组成的串,前缀中1始终多于0.
求卡特兰数但是数据是1000000;
代码:
//C(n+m,n)-C(n+m,n+1)=(n+m)!*(n+1-m)/m!*(n+1)!; //卡特兰数,数据太大。n个1,m个0,从(0,0)出发可以将1看作是向上走,0看作是向右走,这样合法的路径必定在直线y=x-1上方且不与他相交 //做(0,0)关于y=x-1的对称点(1,-1),从(1,-1)出发到终点(m,n)的路径必定与直线相交,将这条路径关于y=x-1对称过去就是从(0,0) //到终点(n,m)不合法的情况。用总的减去就行 //求n,n!质因数模板 #include<bits\stdc++.h> using namespace std; typedef long long ll; #define mod 20100501 #define maxm 2000006 #define maxn 1000006 int p[maxn]; int prime[maxn],res,num; bool is_prime[maxm]; void get_prime() //得到素数表 { prime[0]=2; res=1; for(int i=3;i<maxm;i+=2) if(!is_prime[i]) { for(int j=i;j<maxm;j+=i) is_prime[j]=1; prime[res++]=i; } } void divide1(int x) //分解x的质因数 { int cnt=0; while(x>1) { while(x%prime[cnt]==0) { p[cnt]++; x/=prime[cnt]; } cnt++; } num=max(num,cnt); } void divide2(int x,bool flag) //分解x!的质因数,flag判断是分子还是分母 { int cnt=0; while(prime[cnt]<=x) { int tem=x; while(tem) { if(flag) p[cnt]+=tem/prime[cnt]; else p[cnt]-=tem/prime[cnt]; tem/=prime[cnt]; } cnt++; } num=max(num,cnt); } ll make(ll x,ll y) //x,y不知为何用int就不行,得到x^y。 { ll ans=1; x%=mod; while(y) //很巧妙 { if(y&1) ans=(ans*x)%mod; x=(x*x)%mod; y/=2; } return ans; } ll get_ans() { ll ans=1; for(int i=0;i<=num;i++) { if(p[i]) ans=make(prime[i],p[i])*ans%mod; } return ans; } int main() { int t,n,m; scanf("%d",&t); get_prime(); while(t--) { num=0; memset(p,0,sizeof(p)); scanf("%d%d",&n,&m); divide1(n+1-m); divide2(n+m,1); divide2(m,0); divide2(n+1,0); ll ans=get_ans(); printf("%lld\n",ans); } return 0; }