题目链接地址:
http://acm.hdu.edu.cn/showproblem.php?pid=3398
对于这道题目,自己彻底无语了.........
首先对于这道题目,解决问题有两步
1) 得到公式 C(N+M,N)-C(N+M,M-1) (利用二维坐标来看这个公式,就很明了了,从(0,0)-->(n,m))
2) 对于求C(N,M),有一个快速质因数分解的方法,这样就把除法变成了很好解决的幂减法问题。
倘若用 C(N+1,M+1)=C(N,M)+C(N+1,M).......显然TLE
当时比赛的时候,我找出了公式,但是接下来,自己就不会做了......囧
今天看了别人的解题报告,我也看了好久才明白那个快速质因数分解是什么意思........
现在有种畅快的感觉。
提交后,发现ac的人中,咱花的时间最高,,,,,,1800+MS
代码:
/*
* File: main.cpp
* Author: mtttt
*
* Created on 2010年5月4日, 下午2:56
*/
#include <iostream>
#include <cstdlib>
using namespace std;
const int N=2000000;
const int mod=20100501;
bool ss[N+5];
int n1[N/10],n2[N/10],n3[N/10],pl[N/10];
int n,m,tot;
void prepare() //筛选法选出素数
{
memset(ss,false,sizeof(ss));
for(int i=2;i*i<=N;i++)
{
if(!ss[i])
for(int j=2;i*j<=N;j++)
ss[i*j]=true;
}
tot=0;
for(int i=2;i<=N;i++)
if(!ss[i]) pl[tot++]=i;
}
void Div(int *t,int k) //k! 用 素数相乘来表示, t[i]表示 t[i]个pl[i]相乘
{
for(int i=0;i<tot;i++) t[i]=0;
for(int i=0;pl[i]<=k&&i<tot;i++)
{
int tp=k;
while(tp/pl[i])
{
t[i]+=tp/pl[i];
tp=tp/pl[i];
}
}
}
long long pp(long long a,long long b) // long long 型
{
if(b==0) return 1;
long long re=pp(a,b/2);
re%=mod;
re=re*re;
re%=mod;
if(b%2) re*=a;
re%=mod;
return re;
}
int main(int argc, char** argv) {
// freopen("11.in","r",stdin);
prepare(); // 先打表,得出素数
int T;
cin>>T;
while(T--)
{
scanf("%d %d",&n,&m);
Div(n1,n+m);
Div(n2,n);
Div(n3,m);
for(int i=0;i<tot;i++)
n1[i]=n1[i]-n2[i]-n3[i]; //相除 变成了 幂相减
long long yy=1;
for(int i=0;i<tot;i++)
{ yy*=pp(pl[i],n1[i]);
yy%=mod;
}
Div(n1,n+m);
Div(n2,n+1);
Div(n3,m-1);
for(int i=0;i<tot;i++)
n1[i]=n1[i]-n2[i]-n3[i];
long long uu=1;
for(int i=0;i<tot;i++)
{ uu*=pp(pl[i],n1[i]);
uu%=mod;
}
yy=yy-uu;
yy=(yy+mod)%mod;
cout<<yy<<endl;
}
return 1;
}
代码不优化了.....无语,太伤了
有个极郁闷的.....就是memset(t,o,sizeof(t))....
后来改成了 for(int i=0;i<tot;i++) t[i]=0;
就对了,不然结果就错了....