$\huge \color{orange}{成魔之路->}$ $\huge \color{purple}{算法提高课题解}$
思路:
$点\ (n,m)\ 关于直线\ y=x+1\ 对称的点是\ (m-1,n+1),答案=C_{n+m}^{n}-C_{n+m}^{n+1}$
$最后用高精度求解\ C_{n+m}^{n}-C_{n+m}^{n+1}$
完整代码
#include<bits/stdc++.h>
using namespace std;
const int N = 10010;
int n, m;
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; primes[j] <= n / i; j++)
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
//返回 x! 中质因子 p 的个数
int get(int x, int p)
{
int res = 0;
while (x)
{
res += x / p;
x /= p;
}
return res;
}
//高精度乘法
void mul(int r[], int &len, int p)
{
int t = 0;
for (int i = 0; i < len; i++)
{
t += r[i] * p;
r[i] = t % 10;
t /= 10;
}
while (t)
{
r[len++] = t % 10;
t /= 10;
}
}
int C(int a, int b, int r[])
{
int len = 1;
r[0] = 1;
for (int i = 0; i < cnt; i++)
{
int p = primes[i];
int s = get(a, p) - get(a - b, p) - get(b, p);
while (s--) mul(r, len, p);
}
return len;
}
//高精度减法
void sub(int a[], int al, int b[], int bl)
{
for (int i = 0; i < al; i++)
{
a[i] -= b[i];
if (a[i] < 0)
{
a[i] += 10;
a[i + 1]--;
}
}
}
int main()
{
init(N - 1);
cin >> n >> m;
int al = C(n + m, n, a);
int bl = C(n + m, n + 1, b);
sub(a, al, b, bl);
int k = al - 1;
while (!a[k]) k--;
while (k >= 0) cout << a[k--];
return 0;
}
int s = get(x, p) - get(y, p) - get(x - y, p);大佬这里为什么要-啊,质因子个数不应该是+吗我想不通
$get(x,p)是分子的质因子p的个数,get(y,p)+get(x-y,p)是分母中质因子p的个数,上下约分就相当于分子中质因子p的个数-分母中质因子p的个数$
额,谢谢啊