[AcWing 887] 求组合数 III

image

复杂度 g(n) log(n) (来自 OI Wiki)

总体复杂度 20×105×log(105)×log(1018)=4×107


点击查看代码
#include<iostream>

using namespace std;
typedef long long LL;
int p;

int qmi(int a, int k)
{
    int res = 1;
    while (k) {
        if (k & 1)  res = (LL) res * a % p;
        k >>= 1;
        a = (LL) a * a % p;
    }
    return res;
}
int C(int a, int b)
{
    if (a < b)  return 0;
    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 (b == 0)     return 1;
    return (LL) C(a % p, b % p) * lucas(a / p, b / p) % p;
}
int main()
{
    int n;
    cin >> n;
    while (n --) {
        LL a, b;
        cin >> a >> b >> p;
        cout << lucas(a, b) << endl;
    }
    return 0;
}

  1. 复杂度分析
    复杂度为 f(p)+g(n) log(n) ,其中,f(p) 为预处理组合数的复杂度, g(n) 为单次求组合数的复杂度,对应于本题中, 没有对组合数进行预处理,没有 f(p) 这一项,g(n) 是单次求组合数的复杂度,由于只有当 a<p , b<p 时,才会执行求组合数的函数,单次求组合数的复杂度为 105×log105log(n) 中的 n 是所要求的 Cmn 中的 n
  2. 卢卡斯定理
    Cab=Ca/pb/pCamodpbmodp (mod p),证明如下:
    (1+x)p=Cp0x0+Cp1x1++Cppxp1+xp (mod p)a=a0p0+a1p1++akpkb=b0p0+b1p1++bkpk(1+x)a=(1+x)a0p0+a1p1++akpk(1+x)a0 (1+xp)a1  (1+xpk)ak ,两边同时求 xb 的系数,可以得到 CabCa0b0 Ca1b1  Cakbk (mod p) ,这个式子和卢卡斯定理的式子是等价的;
posted @   wKingYu  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
欢迎阅读『[AcWing 887] 求组合数 III』
点击右上角即可分享
微信分享提示