(AcWing)求组合数 III

给定 n 组询问,每组询问给定三个整数 a,b,p,其中 p 是质数,请你输出 Cbamodp 的值。

输入格式

第一行包含整数 n。

接下来 n 行,每行包含一组 a,b,p。

输出格式

共 n 行,每行输出一个询问的解。

数据范围

1≤n≤20,
1≤b≤a≤10^18,
1≤p≤10^5,

输入样例:

3
5 3 7
3 1 5
6 4 13

输出样例:

3
3
2
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;

LL a, b; // 输入的参数a和b
int p;   // 模数p

LL qmi(LL a, LL b, int p)
{
    LL res = 1;
    while (b)
    {
        if (b & 1) res = res * a % p; // 如果b的二进制表示最低位为1,则将res乘以a并取模p
        a = a * a % p;               // 将a平方并取模p,相当于a^2 mod p
        b >>= 1;                     // 右移一位,相当于除以2
    }
    return res;
}

LL C(int a, int b, int p)   //通过组合数公式求组合数C(a, b)
{
    if (a < b) return 0;     // 如果a小于b,无法计算组合数,返回0
    
    LL fenzi = 1, fenmu = 1; // 分子和分母的初始值都为1
    for (int i = a, j = 1; j <= b; j++, i--)
    {
        fenzi = fenzi * i % p; // 计算分子的阶乘
        fenmu = fenmu * j % p; // 计算分母的阶乘
    }

    return fenzi * qmi(fenmu, p - 2, p) % p; // 返回组合数C(a, b) mod p
}

LL lucas(LL a, LL b, int p)
{
    if (a < p && b < p) return C(a, b, p); // 如果a和b都小于p,直接计算组合数C(a, b)
    else return C(a % p, b % p, p) * lucas(a / p, b / p, p) % p; // 否则使用Lucas定理递归地计算
}

int main()
{
    int n;
    cin >> n; // 读取数据组数
    while (n--)
    {
        cin >> a >> b >> p;   // 读取参数a、b和模数p
        cout << lucas(a, b, p) << endl; // 计算并输出结果
    }
}

猜你喜欢

转载自blog.csdn.net/GF0919/article/details/131962093
今日推荐