• 多项式求逆


    概述

    对于多项式 f(x)。

    求逆:若存在 g(x) 满足 f(x)g(x) ≡ 1 (mod xn), 则称 g(x) 为 f(x) 在模 xn 意义下的逆元, 记作 f-1(x)。

    对数:可以将其对数函数看做其与麦克劳林级数的复合:

    [ln(1 - f(x)) = - sum_{i=1}^{+infty} frac{f^i(x)}{i} \ ln(1 + f(x)) = sum_{i=1}^{+infty} frac{(-1)^{i-1}f^i(x)}{i} ]

    指数:

    [e^{f(x)} = sum_{i=0}^{+infty} frac{f^i(x)}{i!} ]


    求逆

    首先, 对于 b>a, A(x) 在模 xb 下的逆元, 同时也是 A(x) 在模 xa 下的逆元。

    于是可以求出模 (x^{2^k}) 下的逆元, 以下介绍倍增法。

    首先, A(x) ≡ c (mod x), c 是一个常数, 则 A-1(x) (mod x) 就是 c-1

    然后, 假设:

    [A(x)B'(x) equiv 1 mod x^{n/2} \ A(x)B(x) equiv 1 mod x^n ]

    由于显然有 (A(x)B(x) equiv 1 mod x^{n/2})

    于是有:(A(x)(B(x)-B'(x)) equiv 0 mod x^{n/2}), 即 (B(x)-B'(x) equiv 0 mod x^{n/2})

    然后两边平方:(B(x)^2 + B'(x)^2 - 2B(x)B'(x) equiv 0 mod x^n)

    模数也可以一起平方的原因, 详见 miskoo的 blog

    然后乘上 A(x) 并移项:(B(x) equiv 2B'(x) - A(x)B'(x)^2 mod x^n)

    这就是倍增的过程了。

    时间复杂度是 (T(n) = T(n/2) + O(nlog n) = O(nlog n)), 注意 (T(n/2)) 前面没有乘以二, 所以总复杂度不是 (O(nlog^2 n))


    实际代码实现的时候, 其实模数的次幂可以是任意正整数(证明同 miskoo 的证明), 只需要求出模 (x^{lceil n/2 ceil}) 下的逆, 就可以用上述方法求出模 (x^n) 下的逆。

    // 交板子过了, 保证正确
    void poly_inv(int deg, int *a, int *b) {
    	if(deg == 1) { b[0] = ksm(a[0], mo-2); return; }
    	poly_inv((deg + 1) >> 1, a, b);
    	int len = 1; while(len < (deg << 1)) len = len << 1;
    	for(int i=0; i<deg; ++i) c[i] = a[i];
    	for(int i=deg; i<len; ++i) c[i] = 0;
    	
    	for(int i=1; i<len; ++i) rv[i] = (rv[i>>1]>>1) | (i&1?len>>1:0);
    	NTT(c, len, 1), NTT(b, len, 1);
    	for(int i=0; i<len; ++i) b[i] = (LL)b[i] * (2ll - (LL)c[i] * b[i] % mo) % mo;
    	NTT(b, len, -1);
    	
    	for(int i=deg; i<len; ++i) b[i] = 0;
    }
    
  • 相关阅读:
    常用语句
    html引入ECharts的两种方式
    最新版Navicate破解激活
    买路由器篇
    关于java8(Stream)的一些用法
    Mybatis联合查询记录,左连接参数操作
    海淘转运事宜记录
    mysql where语句多条件查询是and和or联合使用bug
    关于mysql中GROUP_CONCAT函数的使用
    关于MySQL存入的时间和取出时间不一致的解决
  • 原文地址:https://www.cnblogs.com/tztqwq/p/14323909.html
Copyright © 2020-2023  润新知