首页 > 其他分享 >关于求阶乘和阶乘逆元的预处理和加速

关于求阶乘和阶乘逆元的预处理和加速

时间:2022-09-05 09:12:19浏览次数:54  
标签:const int res rhs operator 逆元 阶乘 return 预处理

因为求逆元的复杂度其实比较高,所以我们要尽可能地少用快速幂求逆元。

在下面代码中只用快速幂求了一次逆元,其余均是线性复杂度。

vector<Z> fac(n + 1, 1), invfac(n + 1);
    for (int i = 1; i <= n; i++) {
        fac[i] = fac[i - 1] * i;  		//阶乘
    }
    invfac[n] = fac[n].inv();  			//唯一一次快速幂求逆元
    for (int i = n; i; i--) {
        invfac[i - 1] = invfac[i] * i;	//阶乘逆元
    }

完整代码(包含重载):

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

constexpr int mod = 1e9 + 7;

template <class T>
T power(T a, int b) {
    T res = 1;
    for (; b; b >>= 1, a *= a)
        if (b & 1)
            res *= a;
    return res;
}

int norm(int x) {
    if (x < 0) x += mod;
    if (x >= mod) x -= mod;
    return x;
}
struct Z {
    int x;
    Z(int x = 0) : x(norm(x)) {}
    int val() const {
        return x;
    }
    Z operator-() const {
        return Z(norm(mod - x));
    }
    Z inv() const {
        assert(x != 0);
        return power(*this, mod - 2);
    }
    Z &operator*=(const Z &rhs) {
        x = ll(x) * rhs.x % mod;
        return *this;
    }
    Z &operator+=(const Z &rhs) {
        x = norm(x + rhs.x);
        return *this;
    }
    Z &operator-=(const Z &rhs) {
        x = norm(x - rhs.x);
        return *this;
    }
    Z &operator/=(const Z &rhs) {
        return *this *= rhs.inv();
    }
    friend Z operator*(const Z &lhs, const Z &rhs) {
        Z res = lhs;
        res *= rhs;
        return res;
    }
    friend Z operator+(const Z &lhs, const Z &rhs) {
        Z res = lhs;
        res += rhs;
        return res;
    }
    friend Z operator-(const Z &lhs, const Z &rhs) {
        Z res = lhs;
        res -= rhs;
        return res;
    }
    friend Z operator/(const Z &lhs, const Z &rhs) {
        Z res = lhs;
        res /= rhs;
        return res;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, k;
    cin >> n >> k;
    vector<Z> fac(n + 1, 1), invfac(n + 1);
    for (int i = 1; i <= n; i++) {
        fac[i] = fac[i - 1] * i;
    }
    invfac[n] = fac[n].inv();
    for (int i = n; i; i--) {
        invfac[i - 1] = invfac[i] * i;
    }

    Z ans = 0;
    for (int i = 0; i <= min(k, n); i++) {
        ans += fac[n] * invfac[i] * invfac[n - i];
    }

    cout << ans.val() << '\n';

    return 0;
}

标签:const,int,res,rhs,operator,逆元,阶乘,return,预处理
From: https://www.cnblogs.com/blockche/p/16656879.html

相关文章

  • CSP-S模拟2(联考) 谜之阶乘 子集 混凝土粉末 排水系统
    rank4040多分?T1:暴力;T2:构造T2:构造出(1--n)的连续整数分成k组,每组的数加起来一样。(n<=1e6)只要能实现一种构造方案,使得3k个连续数字分k组可以达到(a+b+c)相同(或2k,很显然......
  • 数论——乘法逆元【未完结】
    NO.1一些含义与定义1.含义在\(\bmodp\)的意义下,\(1\)个数如果有乘法逆元\(x\),那么除以\(a\)相当于乘\(x\)。2.为什么要有乘法逆元当我们求\((a/b)\bmodp\)......
  • 信息学一本通 1173:阶乘和
    时间限制:1000ms      内存限制:65536KB提交数:16559   通过数:8405【题目描述】用高精度计算出S=1!+2!+3!+…+n!(n≤100)S=1!+2!+3!+…+n!(n≤100),......
  • 信息学奥赛一本通 1172:求10000以内n的阶乘
    时间限制:1000ms      内存限制:65536KB提交数:34265   通过数:10018【题目描述】求<spanid="MathJax-Span-2"class="mrow"><spanid="MathJax......
  • 793. 阶乘函数后 K 个零
     labuladong题解思路难度困难187收藏分享切换为英文接收动态反馈 f(x) 是 x! 末尾是0的数量。回想一下 x!=1*2*3*...*x,且 0!=1 。例如, ......
  • 预处理的艺术
    预处理的艺术以下默认合并答案是\(O(1)\)的\(O(n\alpha(n))-O(1)\)的ST表这个非常\(naive\),对于规模为\(O(n)\)的问题,我们以\(O(\logn)\)为块长分块,块间建立ST......
  • 数据预处理
    data.xlsx数据如下1#-*-coding:utf-8-*-2#我们必须进行数据预处理它直接关系到分析结果的准确性处理缺失值数据重复值3#检查缺失值检测缺失值最简单......
  • css预处理器
    CSS预编译工具有stylus,sass,less为什么会出现CSS预编译器这个东西呢?这就要谈到CSS的不足了:没有变量(新的规范已经支持了),不支持嵌套,编程可以力较弱,代码复使用性差。这些......
  • AFNI 步骤4-命令和预处理
    第一部分AFNI命令和uber_subject.py的使用略 第二部分时间矫正在扫描过程中,从第一个切片到最后一个切片之间存在一定的时间差,导致采集到的数据并不是......
  • leetcode-793. 阶乘函数后 K 个零
    793.阶乘函数后K个零图床:blogimg/刷题记录/leetcode/793/刷题代码汇总:https://www.cnblogs.com/geaming/p/16428234.html题目思路首先我们令\(zeta(x)\)为\(x!\)......