AcWing 887. Lucas定理求组合数(模板)

题目链接:点击这里

在这里插入图片描述

Lucas定理

p p 是质数,则对于任意整数 1 m n 1 \leq m \leq n 有:
C n m C n   m o d   p m   m o d   p C n / p m / p   ( m o d   p ) C_n^m \equiv C_{n\ mod\ p}^{m\ mod \ p}*C_{n/p}^{m/p}\ (mod\ p)
也就是把 n n m m 表示成 p p 进制数,对 p p 进制下的每一位分别计算组合数,最后再乘起来。

#include<iostream>
#include<cstdio>

using namespace std;
typedef long long ll;

int p;

int qmi(int a ,int b)	 // 快速幂模板
{
    int res = 1;
    while(b)
    {
        if(b & 1)   res = (ll)res * a % p;
        a = (ll)a * a % p;
        b >>= 1;
    }
    return res;
}

int C(int a, int b)		// 通过定义求组合数C(a, b)
{
    int res = 1;
    for(int i = 1, j = a; i <= b; ++i, --j)
    {
        res = (ll)res * j % p;
        res = (ll)res * qmi(i, p - 2) % p;
    }
    return res;
}

int lucas(ll a, ll b)
{
    if(a < p && b < p)  return C(a, b);
    return (ll)C(a % p, b % p) * lucas(a / p, b / p) % p;
}

int main()
{
    int n;
    scanf("%d", &n);
    
    while(n--)
    {
        ll a, b;
        scanf("%lld%lld%d", &a, &b, &p);
        
        printf("%d\n", lucas(a, b));
    }
    
    return 0;
}
发布了811 篇原创文章 · 获赞 127 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/104813790