一.题目链接
二.思路
思路参考:https://blog.csdn.net/weixin_42638946/article/details/115751984
三.代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;//位数
int primes[N], cnt;
bool st[N];
int a[N], b[N];//存储两个组合数的答案
void init(int n)
{
for(int i = 2; i <= n; i ++)
{
if(!st[i]) primes[cnt ++] = i;
for(int j = 0; i * primes[j] <= n; j ++)
{
st[i * primes[j]] = true;
if(i % primes[j] == 0) break;
}
}
}
int get(int n, int p)
{
int s = 0;
while(n)
{
s += n / p;
n /= p;
}
return s;
}
//高精度乘法
void mul(int r[], int &len, int x)
{
int t = 0;
for(int i = 0; i < len; i ++)
{
t += r[i] * x;
r[i] = t % 10;
t /= 10;
}
while(t)
{
r[len ++] = t % 10;
t /= 10;
}
}
//高精度减法
void sub(int a[], int al, int b[], int bl)
{
int t = 0;
for(int i = 0; i < al; i ++)
{
a[i] -= t + b[i];
if(a[i] < 0) a[i] += 10, t = 1;
else t = 0;
}
}
int C(int a, int b, int r[N])
{
int len = 1;//记录答案的长度
r[0] = 1;//一开始是1;
for(int i = 0; i < cnt; i ++)
{
int p = primes[i];
int s = get(a, p) - get(b, p) - get(a - b, p);
while(s --) mul(r, len, p);
}
return len;
}
int main()
{
init(N - 1);
int n, m;
cin >> n >> m;
int al = C(n + m, n, a);//将C(n + m, n)的结果放到a数组里面返还长度
int bl = C(n + m, m - 1, b);//将C(n + m, m - 1)的结果放到b数组里面返还长度
//因为a, b都是高精度。
sub(a, al, b , bl);//答案存到a里面
int k = al - 1;
while(!a[k] && k > 0) k --;//去除前导0
while(k >= 0) printf("%d", a[k --]);//输出答案
return 0;
}
四.总结
- 如何求组合数的相关总结
- 本题的高精度写法非常锻炼写法,需要反复推敲。