Hdu3398 String

    技术2026-06-06  6

    String

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 920    Accepted Submission(s): 231

    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

    Aut h or

    l xhgww

        好久没做数学题了,表示很生疏,木有手感……看大牛们的解题报告完成的……orz …顺便膜拜一下……

    这题的意思是要求满足如下要求字符串的个数,要求是由m 0 n 1 组成,而且对于该字符串的任意前缀满足 1 的个数不小于 0 的个数。

    可以这么考虑,设一个直角坐标系,刚开始的时候在原点,假设如果字符串第 i个是 0 的话,那么就向右移动一个单位,如果是 1 的话,向上移动一个单位,那么最终显然将移动到( m n )处,那么对于由 m 0 n 1 组成的字符串的个数即为 C(m+n,m)

    又要要求1 的个数大于 0 的个数,我们可以理解为从 (0,0) (m,n) 的路径不和 y=x-1 相交,也就是说,不满足要求的路径必和 y=x-1 相交,因此,做 (0,0) 点关于 y=x-1 的对称点即为 (1,-1) ,因此,从 (1,-1) (m,n) 的路径必过 y=x-1 ,那么不满足的路径即为从 (1,-1) (m,n) 的路径与 y=x-1 第一次相交的部分关于 y=x-1 翻转过去再接上后面的路径,所以不满足条件的路径数为从 (1,-1) (m,n) 的路径数即为 C(m+n,n+1)

    所以最终结果就是C(m+n,n)-C(m+n,n+1)

    最后因为数字比较大,用int64 ,然后还需要质因子分解求值。

    代码如下

    #include <stdio.h> #define MOD 20100501 typedef struct { __int64 val,num; }Pri; __int64 prime[2000005]; Pri a[200000]; __int64 up; void Isprime() { __int64 k,i,j; up=0; for (i=0;i<2000003;i++) { prime[i]=true; } for (i=2;i<2000003;i++) { if (prime[i]==false) continue; k=i; while(i*k<=2000000) { prime[i*k]=false; k++; } a[up++].val=i; } } void Cplus(__int64 t) { __int64 i,s; __int64 k; for (i=0;i<up;i++) { s=0; k=a[i].val; while(t>=k) { s=s+t/k; k=k*a[i].val; } a[i].num=a[i].num+s; } } void Cminus(__int64 t) { __int64 i,s; __int64 k; for (i=0;i<up;i++) { s=0; k=a[i].val; while(t>=k) { s=s+t/k; k=k*a[i].val; } a[i].num=a[i].num-s; } } __int64 Count(__int64 n,__int64 p) { __int64 i,j,s; s=1; while(n!=0) { if (n%2==1) { s=s*p%MOD; } p=p*p%MOD; n=n/2; } return s; } void Test() { int i; for (i=0;i<50;i++) { printf("%I64d %I64d/n",a[i].val,a[i].num); } } int main() { __int64 i,t,j,n,T,m; __int64 ans; scanf("%I64d",&T); Isprime(); while(T--) { scanf("%I64d%I64d",&n,&m); for (i=0;i<up;i++) { a[i].num=0; } Cplus(m+n); // Test(); Cminus(m); Cminus(n+1); t=n+1-m; for (i=0;i<up;i++) { while(t%a[i].val==0) { a[i].num++; t=t/a[i].val; } if (t==1) break; } ans=1; for (i=0;i<up;i++) { ans=ans*Count(a[i].num,a[i].val)%MOD; } printf("%I64d/n",ans); } return 0; }

    最新回复(0)