给定 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; // 计算并输出结果
}
}