链接:http://acm.ocrosoft.com/problem.php?cid=2001&pid=4
题目描述
猩猩,骆驼,还有泡泡经常喜欢在饭后到操场上散步,由于猩猩的走路姿势最突出最显眼,理所应当的成为他们中的主角,所以我的题目就说猩猩散步了。(骆驼和泡泡别有意见哈,和猩猩争啥……) 当然,话说回来,猩猩在OI上的能力也是不容低估的,你看,散步时还会想一道与此相关的问题,这是道经典的不能再经典的问题了。 在一个m×n的矩阵上,猩猩在左下角的顶点出现了,他只能沿着路径向上或者向右走,他的目标是“蠕动”到右上角的顶点,问他有多少路径可以选择。嗯,这个、这个、这个似乎地球人都知道怎么做,但是请注意,我有个条件没给呢!m和n现在的最大范围是50000,这可怎么办?仔细想想吧。
输入
只有一行,包含两个整数m和n,其上限均为50000
输出
由于最后的答案数目过大,所以只检查后100位,输出时每行十个数字,没空格间隔,共十行,如果答案位数没超过100位,则需要在空位上补0。
样例输入
7 4
样例输出
0000000000 0000000000 0000000000 0000000000 0000000000 0000000000 0000000000 0000000000 0000000000 0000000330
题解:就是简单的求c(n,n+m)的问题,主要还是看大数的处理,普通的大数会被卡(不知道为什么,可能是常数的问题),这里用到了素数大数乘,比如样例求C(4,11)=11×10×9×8÷4÷3÷2÷1
可以转化成(11^1)×(2^1×5^1)×(3^2)×(2^3)÷(2^2)÷(3^1)÷(2^1)
题解:
#include<bits/stdc++.h>
using namespace std;
long long x,k,ans=1,s=0,l=0;
int a[100005];
bool prime[100005];
int p[1000005];
void mu(int q)
{
for(int i=1;i<=l;i++)
p[i]=p[i]*q;
int i=1;
while(i<=l||p[i]>10)
{
p[i+1]=p[i+1]+p[i]/10;
p[i]=p[i]%10;
i++;
}
l=i;
while(!p[l])
l--;
}
void mu2(int q)
{
for(int i=1;i<=sqrt(q)+1;i++)
{
if(prime[i])
{
while(q%i==0)
{
a[i]++;
q=q/i;
}
}
}
if(q>0)
a[q]++;
}
void di(int q)
{
for(int i=1;i<=sqrt(q)+1;i++)
{
if(prime[i])
{
while(q%i==0)
{
a[i]--;
q=q/i;
}
}
}
if(q>0)
a[q]--;
}
int main()
{
p[1]=1;
l=1;
cin>>k>>x;
ans=k+x;
for(int i=2;i<=ans;i++)
prime[i]=true;
for(int i=2;i<=ans;i++)//筛素数
{
if(prime[i])
{
for (int j=i;j<=ans/i;j++)
prime[i*j]=false;
}
}
for(int i=1;i<=min(k,x);i++)//ans*(ans-1)*……min(k,x)
mu2(ans-i+1);
for(int i=1;i<=min(k,x);i++)//min(k,x)!
di(i);
for(int i=1;i<=ans;i++)
{
for(int j=1;j<=a[i];j++)
mu(i);
}
for(int i=100;i>=1;i--)//输出
{
if(i%10!=1)//补零
cout<<p[i];
else
cout<<p[i]<<endl;
}
return 0;
}