蒟蒻也能写出来的AC代码!显然题目是让求
0!m!+1!(m+1)!+2!(m+2)!+⋯+(n−1)!(m+n−1)!
易通分为
0!(m+n−1)!m!+1!(m+n−1)!(m+1)!+⋯+(n−1)!(m+n−1)!(m+n−1)!(m+n−1)!
观察到分母是个奇大无比的数,倘若是硬算分母最后再除免不了高精除高精。哦我的老伙计,看在梅林的胡子的面子上,你一定不想写它的。于是我们就有一个优化:先将分母分解质因数,最后进行高精除低精约分。
再考虑分子。可以发现,分子可以化成好多个
xyz
,且如果我们知道某一项,那么其下一项可以通过
x
乘某个数,
细节也是需要注意的。这里注意一点,我的除法为了这道题做了点改动,即倘若有操作bool qaq=a/b;
其中a为高精度数,b为int,要是
b|a
则有qaq被赋值true, 且a被b除掉。否则,qaq被赋值为false,且a不发生改变。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
struct bigInt{
int num[2500], len;
bigInt operator+(bigInt &x)const{
bigInt re;
memset(re.num, 0, sizeof(re.num));//不加初始化大约会有奇怪的错误,我调了一个小时QAQ
re.len = max(len, x.len);
for(int i=1; i<=re.len; i++)
re.num[i] = num[i] + x.num[i];
int jw=0;
for(int i=1; i<=re.len; i++){
re.num[i] += jw;
jw = re.num[i] / 10;
re.num[i] %= 10;
}
if(jw)
re.num[++re.len] = jw;
return re;
}
bigInt operator*(int &x)const{
bigInt re;
memset(re.num, 0, sizeof(re.num));
re.len = len;
for(int i=1; i<=re.len; i++)
re.num[i] = num[i] * x;
int jw=0;
for(int i=1; i<=re.len; i++){
re.num[i] += jw;
jw = re.num[i] / 10;
re.num[i] %= 10;
}
while(jw){
re.num[++re.len] = jw%10;
jw /= 10;
}
return re;
}
bool operator/(const int &x){
bigInt re;
memset(re.num, 0, sizeof(re.num));
re.len = len;
int tw=0;
for(int i=len; i>=1; i--){
tw = tw * 10 + num[i];
re.num[i] = tw / x;
tw %= x;
}
if(tw) return false;//除不干净
while(!re.num[re.len]) re.len--;
if(!re.len) re.len++;
len = re.len;
for(int i=1; i<=re.len; i++)
num[i] = re.num[i];
return true;
}
bigInt prt(){//输出函数
for(int i=len; i>=1; i--)
putchar(num[i]+'0');
putchar('\n');
}
}fz, fztemp, fm;//fz表示分子,fm表示分母,fztemp表示当前处理分子的那一项
vector<int> zys;//质因数
int n, m;
bool isp[1005];
void shai(){//筛法筛质数
memset(isp, true, sizeof(isp));
isp[0] = isp[1] = false;
for(int i=2; i<=1000; i++)
if(isp[i])
for(int j=i+i; j<=1000; j+=i)
isp[j] = false;
}
void makezys(int x){//对某个数分解质因数
for(int i=2; i<=x; i++)
if(isp[i])
while(x%i==0){
zys.push_back(i);
x /= i;
}
}
int main(){
cin>>n>>m;
shai();
fztemp.len = fm.len = 1;
fztemp.num[1] = fm.num[1] = 1;
fz.len = 1;
fz.num[1] = 0;
for(int i=1; i<=n+m-1; i++)
makezys(i);
for(int i=m+1; i<=n+m-1; i++)
fztemp = fztemp * i;//先处理出0!*(n+m-1)!/m!
for(int i=0; i<=n-1; i++){
if(i) fztemp / (m+i);
if(i) fztemp = fztemp * i;//为了避免0!的尴尬加上if(i)
fz = fz + fztemp;
}
for(int i=0; i<zys.size(); i++){
if(fz/zys[i]) ;
else fm = fm*zys[i];//不可约分,只好在分母中保留它了
}
fz.prt();
fm.prt();
return 0;
}