洛谷 P3807 【模板】卢卡斯定理

任重而道远

题目描述

给定n,m,p( 1\le n,m,p\le 10^51n,m,p105 )

求 C_{n+m}^{m}\ mod\ pCn+mm mod p

保证P为prime

C表示组合数。

一个测试点内包含多组数据。

输入输出格式

输入格式:

第一行一个整数T( T\le 10T10 ),表示数据组数

第二行开始共T行,每行三个数n m p,意义如上

输出格式:

共T行,每行一个整数表示答案。

AC代码:
#include<cstdio>
#include<cstring>
using namespace std;

typedef long long ll;
const int N = 150000;
ll fac[N], m, n;
int T, p;

ll read () {
    ll x = 0, jud = 1;
    char c = getchar ();
    while (c < '0' || c > '9') {
        if (c == '-') jud = -1;
        c = getchar ();
    }
    while (c >= '0' && c <= '9') {
        x = x * 10 + c - '0';
        c = getchar ();
    }
    return x * jud;
}

void init () {
    fac[0] = 1;
    for (int i = 1; i <= p; i++)
      fac[i] = fac[i - 1] * i % p;
}

void exgcd ( ll a, ll b, ll& cd, ll& x, ll& y ) {
    if (b == 0) {
        x = 1; y = 0;
        cd = a;
    } else {
        exgcd (b, a % b, cd, y, x);
        y -= x * (a / b);
    }
}

ll C ( ll n, ll m ) {
    if (m > n) return 0;
    ll x, y, cd;
    exgcd (fac[m] * fac[n - m], p, cd, x, y);
    x = (x % p + p) % p;
    return fac[n] * x % p;
}

ll Lucas ( ll n, ll m ) {
    if (m == 0)
      return 1;
    return C (n % p, m % p) * Lucas (n / p, m / p) % p;
}

int main () {
    scanf ("%d", &T);
    while (T--) {
        n = read (); m = read ();
        scanf ("%d", &p);
        init ();
        printf ("%lld\n", Lucas (n + m, m));
    }
}

猜你喜欢

转载自blog.csdn.net/INTEGRATOR_37/article/details/80139454