题目描述
猩猩,骆驼,还有泡泡经常喜欢在饭后到操场上散步,由于猩猩的走路姿势最突出最显眼,理所应当的成为他们中的主角,所以我的题目就说猩猩散步了。(骆驼和泡泡别有意见哈,和猩猩争啥……) 当然,话说回来,猩猩在OI上的能力也是不容低估的,你看,散步时还会想一道与此相关的问题,这是道经典的不能再经典的问题了。 在一个m×n的矩阵上,猩猩在左下角的顶点出现了,他只能沿着路径向上或者向右走,他的目标是“蠕动”到右上角的顶点,问他有多少路径可以选择。嗯,这个、这个、这个似乎地球人都知道怎么做,但是请注意,我有个条件没给呢!m和n现在的最大范围是50000,这可怎么办?仔细想想吧。
.
输入
只有一行,包含两个整数m和n,其上限均为50000
输出
由于最后的答案数目过大,所以只检查后100位,输出时每行十个数字,没空格间隔,共十行,如果答案位数没超过100位,则需要在空位上补0。
样例输入
7 4
样例输出
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000000
0000000330
#include<iostream>
#include <cstring>
using namespace std;
const long a[66]= {0 ,2 ,3 ,5 ,7 ,11 ,13 ,17 ,19 ,23 ,
29 ,31 ,37 ,41 ,43 ,47 ,53 ,59 ,61 ,67 ,
71 ,73 ,79 ,83 ,89 ,97 ,101,103,107,109,
113,127,131,137,139,149,151,157,163,167,
173,179,181,191,193,197,199,211,223,227,
229,233,239,241,251,257,263,269,271,277,
281,283,293,307,311,313};
void mul(long a[1000],long n)
{ long i;
for (i=1; i<=a[0]; i++)
a[i]=a[i]*n;
for (i=1; i<a[0]; i++) {
a[i+1]+=a[i]/10;
a[i]%=10;
}
while (a[a[0]]>9) {
a[a[0]+1]=a[a[0]]/10;
a[a[0]]%=10; a[0]++;
}
if (a[0]>101)
a[0]=101;
}
int main(){
long i,j,n,m,all,h[200000],nn,mm,ans[1000];
scanf("%ld %ld",&n,&m);
all = n + m;
memset(h,0,sizeof(h));
for (i = n+1; i <= all; i++)
{
nn=i;
for (j = 1; j <= 65; j++)
{
while (nn%a[j] == 0)
{h[a[j]]++; nn/=a[j];
if (nn==1)
break;}
if (nn==1)
break;}
if (nn!=1)
h[nn]++;
}
for (i=1; i<=m; i++)
{
mm=i;
for (j=1; j<=65; j++)
{
while (mm%a[j]==0)
{h[a[j]]--; mm/=a[j];
if (mm==1)
break;}
if (mm==1)
break;}
if (mm!=1)
h[mm]--;
}
ans[0]=1;
ans[1]=1;
for (i=1; i<=100000; i++)
while (h[i]>0) {
mul(ans,i);
h[i]--;
}
for (i=100; i>=1; i--) {
printf("%ld",ans[i]);
if (i%10==1)
printf("\n");
}
}
题目做多了,人都麻木了,这么简单的逻辑都无法快速看出来。。。
求的是C(n+m,m)也可以写成C(n+m,n)是一样的,具体编程思路就是先开个素数表记录平方在100000以内的素数,然后把分子每个因数分解质因数,相应的HASH表+1,而分母分解时则-1,如果分解到最后剩下的不是1,那么剩下的数肯定也是一个质数,直接相应HASH+1或-1.最后HASH里不为0的都去乘,只保留最后100位,速度不会慢的