首页 > 代码库 > *HDU3398 数学

*HDU3398 数学

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;
}

 

*HDU3398 数学