HDU 3398 String

题目大意:一个长为n的01字符串,使前缀任意0的数量不大于1的数量,求方案数……

题解:高一模拟赛时做过,是卡特兰数的几何意义,将字符串变为矩阵寻路,不可越过对角线,那么就是卡特兰数了,C(n+m, n)-C(n+m,n+1)=(n+1-m)(n+m)!/(n+1)!m!。需要注意的是取模的问题,如果用高精度最后取模会太慢了,会超时,所以直接用power定理分解素数,对于每个素数分别算幂,取模相乘即可。

#include <cstdio>  
#include <cstring>   
const int N=1000001;  
using namespace std;  
typedef long long  LL;   
int pri[N*2+1],p[N*2+1],tot;
int cal(int pr,int n){int rs=0;while(n)n/=pr,rs+=n;return rs;}  
void initp(){  
    memset(pri,0,sizeof pri); tot=0;  
    for(int i=2;i<=N*2;i++){  
        if(pri[i])continue; p[tot++]=i; 
        for(int j=i*2;j<=N*2;j+=i)pri[j]=1;  
    }  
}   
int main(){  
    int cas,n,m; initp();  
    scanf("%d",&cas);  
    while(cas--){  
        scanf("%d%d",&n,&m);         
        LL rs=1; int nm=n-m+1;  
        for(int i=0;i<tot&&p[i]<=n+m;i++){  
            int cnt=0;  
            while(nm%p[i]==0)nm/=p[i],cnt++;  
            int ipow=cnt+cal(p[i],n+m)-cal(p[i],n+1)-cal(p[i],m);  
            for(int j=1;j<=ipow;j++){  
                rs=(rs*p[i])%20100501;  
            }  
        }  
        printf("%lld\n",rs);  
    }  
    return 0;  
}  
posted @ 2014-04-15 20:25  forever97  阅读(207)  评论(0编辑  收藏  举报