题目链接:https://www.acwing.com/problem/content/description/889/
时/空限制:1s / 64MB

题目描述

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

输入格式

第一行包含整数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

解题思路

题意:的值。
思路:

  • 100000组, 1 <= b <= a <= 2000, 递推 -> O(N^2).
  • 10000组, 1 <= b <= a <= 10^5, 预处理 -> O(NlogN).
  • 20组, 1 <= b <= a <= 10^18, p <= 10^5, 卢卡斯定理(lucas)

Accepted Code:

/* 
 * @Author: lzyws739307453 
 * @Language: C++ 
 */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int Fast_Power(int a, int b, int p) {
    int res = 1;
    while (b) {
        if (b & 1)
            res = 1ll * res * a % p;
        a = 1ll * a * a % p;
        b >>= 1;
    }
    return res;
}
int Com_Num(int a, int b, int p) {
    int res = 1;
    for (int i = 1, j = a; i <= b; i++, j--)
        res = 1ll * res * j % p * Fast_Power(i, p - 2, p) % p;
    return res;
}
int lucas(ll a, ll b, int p) {
    if (a < p && b < p)
        return Com_Num(a, b, p);
    return 1ll * Com_Num(a % p, b % p, p) * lucas(a / p, b / p, p) % p;
}
int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        int p;
        ll a, b;
        scanf("%lld%lld%d", &a, &b, &p);
        printf("%d\n", lucas(a, b, p));
    }
    return 0;
}