卢卡斯定理(用于解决组合数取模问题【模数必须为质数】)

    int qpow(int a, int b, int p) {
        int res = 1;
        while (b) {
            if (b & 1)
                res = res*a%p;
            a = a*a%p;
            b >>= 1;
        }
        return res;
    }
    
    int C(int a, int b, int p) {
        if (b > a) 
            return 0;
        int res = 1;
        for (int i = 1, j = a; i <= b; i++, j--) {
            res = res*j%p;
            res = res*qpow(i, p-2, p)%p;
        }
        return res;
    }
    
    int lucas(int a, int b, int p) {
        if (a<p && b < p)
            return C(a, b, p);
        return C(a%p, b%p, p)*lucas(a/p, b/p, p)%p;
    }
    
    signed main() {
        int n;
        cin >> n;
        while (n--) {
            int a, b, p;
            cin >> a >> b >> p;
            //b上a下
            cout << lucas(a, b, p) << "\n";
        }
        return 0;
    }
    

    扩展卢卡斯定理(用于解决组合数取模问题【模数可以为任意大于1的整数】)

    void exgcd(int a, int b, int &x, int &y) {
        if (!b)
            return (void)(x=1, y=0);
        exgcd(b, a%b, x, y);
        int t = x; x = y;
        y = t-a/b*y;
    }
    
    int inv(int a, int p) {
        int x, y;
        exgcd(a, p, x, y);
        return (x+p)%p;
    }
    
    int lcm(int a, int b) {
        return a/__gcd(a, b)*b;
    }
    
    int qpow(int a, int b, int p) {
        int res = 1;
        while (b) {
            if (b & 1) 
                res = res*a%p;
            a = a*a%p;
            b >>= 1;
        }
        return res;
    }
    
    int F(int n, int p, int pk) {
        if (!n) 
            return 1;
        int rou = 1, rem = 1;
        for  (int i = 1; i <= pk; i++) {
            if (i % p)
                rou = rou*i%p;
        }
        rou = qpow(rou, n/pk, pk);
        for (int i = pk*(n/pk); i <= n; i++) {
            if (i % p)
                rem = rem*(i%pk)%pk;
        }
        return F(n/p, p, pk)*rou%pk*rem%pk; 
    }
    
    int G(int n, int p) {
        if (n < p) 
            return 0;
        return G(n/p, p)+(n/p); 
    }
    
    int C_PK(int n, int m, int p, int pk) {
        int fz = F(n, p, pk);
        int fm1 = inv(F(m, p, pk), pk);
        int fm2 = inv(F(n-m, p, pk), pk);
        int mi = qpow(p, G(n, p)-G(m, p)-G(n-m, p), pk);
        return fz*fm1%pk*fm2%pk*mi%pk; 
    }
    
    int exlucas(int n, int m, int p) {
        int A[1005], B[1005];
        int kkk = p, tot = 0;
        for (int t = 2; t*t <= p; t++) {
            if (!(kkk%t)) {
                int pk = 1;
                while (!(kkk%t)) {
                    pk *= t;
                    kkk /= t;
                }
                A[++tot] = pk, B[tot] = C_PK(n, m, t, pk);
            }
        }
        if (kkk != 1) {
            A[++tot] = kkk;
            B[tot] = C_PK(n, m, kkk, kkk);
        }
        int ans = 0;
        for (int i = 1; i <= tot; i++) {
            int M = p/A[i], T = inv(M, A[i]);
            ans = (ans+B[i]*M%p*T%p)%p;
        }
        return ans;
    }
    
    signed main() {
        int a, b, p;
        cin >> a >> b >> p;
        cout << exlucas(a, b, p) << "\n";
        return 0;
    }