c++ - 两个二项式系数的 GCD 模 10^9 + 7

标签 c++ algorithm math number-theory binomial-coefficients

给定0 ≤ k ≤ n ≤ 5000000 ≤ l ≤ m ≤ 500000

我需要共同计算 GCD(C(n, k), C(m, l)) 模 10^9 + 7。

我的尝试:

我想到了 fourmula 的技巧: C(n, k) = n*(n-1)*...*(n-k+1)/k!

例如,假设 l >= k: GCD( C(n, k), C(m, l) ) = = GCD( n*(n-1)*...*(n-k+1)/k!, m*(m-1)*...*(m-l+1)/l! ) = = GCD( n*(n-1)*...*(n-k+1)*(k + 1)*...*l/l!, m*(m-1)*...* (m-l+1)/l!) = = GCD( n*(n-1)*...*(n-k+1)*(k + 1)*...*l, m*(m-1)*...*(m- l+1) )/l!

l! 的二进制求幂取反为 10^9 + 5 没问题,但我不知道如何继续。

这个 (k + 1)*...*l 部分毁了一切。如果乘数之间存在交集,我可以找到一些好处 n*(n-1)*...*(n-k+1)m*(m-1)*...*(m-l+1), 但如果不是,则整个 GCD 必须包含在此 (k + 1)*...*l 部分中。

然后呢?对剩余乘数使用 native GCD 算法? 由于需要计算它们的乘积,又太长了,所以上面的操作看起来毫无意义。

我走的路对吗? 有什么技巧可以解决这个问题吗?

最佳答案

根据 juvian 的建议,这非常简单。我怎么没有想到分解的想法!

我的 C++ 代码如下:

#include <iostream>
#include <algorithm>

#define NMAX 500000
#define MOD 1000000007

using namespace std;


long long factorial(long long n)
{
    long long ans = 1;
    for (int i = 2; i <= n; i++)
        ans = ans * i % MOD;
    return ans;
}

long long binPow(long long num, int p)
{
    if (p == 0)
        return 1;

    if (p % 2 == 1)
        return binPow(num, p - 1) * num % MOD;
    if (p % 2 == 0)
    {
        long long b = binPow(num, p / 2);
        return b * b % MOD;
    }
}

void primesFactorize(long long n, long long primes[])
{
    for (int d = 2; d * d <= n; d++)
        while(n % d == 0)
        {
            n /= d;
            primes[d]++;
        }
    if (n > 1) primes[n]++;
}

long long primes1[NMAX];
long long primes2[NMAX];

int main()
{
    long long n, k, m, l;

    cin >> k >> n >> l >> m;

    if (k > l)
    {
        swap(n, m);
        swap(k, l);
    }

    for (int i = n - k + 1; i <= n; i++)
        primesFactorize(i, primes1);

    for (int i = k + 1; i <= l; i++)
        primesFactorize(i, primes1);

    for (int i = m - l + 1; i <= m; i++)
        primesFactorize(i, primes2);

    for (int i = 2; i <= max(n, m); i++)
        primes1[i] = min(primes1[i], primes2[i]);

    long long ans = 1;
    for (int i = 2; i <= max(n, m); i++)
        for (int j = 1; j <= primes1[i]; j++)
            ans = ans * i % MOD;

    ans = ans * binPow(factorial(l), MOD - 2) % MOD;

    cout << ans << endl;
    return 0;
}

关于c++ - 两个二项式系数的 GCD 模 10^9 + 7,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51595642/

相关文章:

c++ - 从 vector 中删除空元素

c++ - 指向 C++ 类成员函数的指针作为全局函数的参数?

c++ - 在 OpenGL 中围绕对象而不是相机周围的对象旋转 'camera'

c++ - 来自并发 HashMap 的迭代器是否安全?

java - 图像比较算法

将区间映射到较小区间的算法

math - Monad 有什么特别之处?

algorithm - 自动选择图例的比例(线性、幂、对数)

Python 截断指数分布

c++ - friend 可以访问 friend 的成员(member),但似乎无法更新 friend 的成员(member)