zoukankan      html  css  js  c++  java
  • Luogu 4725 【模板】多项式对数函数

    继续补全模板。

    要求

    $$g(x) = ln f(x)$$

    两边求导,

    $$g'(x) = frac{f'(x)}{f(x)}$$

    然后左转去把多项式求导和多项式求逆的模板复制过来,就可以计算出$g'(x)$,接下来再对$g'(x)$求不定积分即可。

    虽然我也不是很会不定积分,但是这就是求导的逆过程,相当于把求完导之后的函数搞回去。

    因为$(a_ix^i)' = ia_ix^{i - 1}$,所以反向算一下就好。

    求导的时间复杂度是$O(n)$,积分的时间复杂度是$O(nlogn)$,总时间复杂度是$O(nlogn)$。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int N = 1 << 18;
    
    int n;
    ll f[N], g[N];
    
    namespace Poly {
        const int L = 1 << 18;
        const ll P = 998244353LL;
    
        int lim, pos[L];
        ll f[L], g[L], h[L];
        
        inline ll fpow(ll x, ll y) {
            ll res = 1;
            for (x %= P; y > 0; y >>= 1) {
                if (y & 1) res = res * x % P;
                x = x * x % P;
            }
            return res;
        }
        
        inline void prework(int len) {
            int l = 0;
            for (lim = 1; lim < len; lim <<= 1, ++l);
            for (int i = 0; i < lim; i++)
                pos[i] = (pos[i >> 1] >> 1) | ((i & 1) << (l - 1));
        }
        
        inline void ntt(ll *c, int opt) {
            for (int i = 0; i < lim; i++)
                if (i < pos[i]) swap(c[i], c[pos[i]]);
            for (int i = 1; i < lim; i <<= 1) {
                ll wn = fpow(3, (P - 1) / (i << 1));
                if (opt == -1) wn = fpow(wn, P - 2);
                for (int len = i << 1, j = 0; j < lim; j += len) {
                    ll w = 1;
                    for (int k = 0; k < i; k++, w = w * wn % P) {
                        ll x = c[j + k], y = w * c[j + k + i] % P;
                        c[j + k] = (x + y) % P, c[j + k + i] = (x - y + P) % P;
                    }
                }
            }
            
            if (opt == -1) {
                ll inv = fpow(lim, P - 2);
                for (int i = 0; i < lim; i++) c[i] = c[i] * inv % P;
            }
        }
        
        void inv(ll *a, ll *b, int len) {
            if (len == 1) {
                b[0] = fpow(a[0], P - 2);
                return;
            }
            
            inv(a, b, (len + 1) >> 1);
            prework(len << 1);
            for (int i = 0; i < lim; i++) f[i] = g[i] = 0;
            for (int i = 0; i < len; i++) f[i] = a[i], g[i] = b[i];
            ntt(f, 1), ntt(g, 1);
            for (int i = 0; i < lim; i++)
                g[i] = g[i] * (2LL - g[i] * f[i] % P + P) % P;
            ntt(g, -1);
            
            for (int i = 0; i < len; i++) b[i] = g[i];
        }
        
        inline void direv(ll *c, int len) {
            for (int i = 0; i < len - 1; i++) c[i] = c[i + 1] * (i + 1) % P;
            c[len - 1] = 0;
        }
        
        inline void integ(ll *c, int len) {
            for (int i = len - 1; i > 0; i--) c[i] = c[i - 1] * fpow(i, P - 2) % P;
            c[0] = 0;
        }
        
        inline void ln(ll *a, ll *b, int len) {
            for (int i = 0; i < len; i++) h[i] = 0;
            inv(a, h, len);
            
    /*        for (int i = 0; i < len; i++)
                printf("%lld%c", h[i], " 
    "[i == n - 1]);    */
            
            for (int i = 0; i < len; i++) b[i] = a[i];
            direv(b, len);
            
    /*        for (int i = 0; i < len; i++)
                printf("%lld%c", b[i], " 
    "[i == n - 1]);    */
    
            prework(len << 1);
            ntt(h, 1), ntt(b, 1);
            for (int i = 0; i < lim; i++) b[i] = b[i] * h[i] % P;
            ntt(b, -1);
            
    /*        for (int i = 0; i < len; i++)
                printf("%lld%c", b[i], " 
    "[i == n - 1]);    */
    
            integ(b, len);
        }
        
    };
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for (; ch > '9'|| ch < '0'; ch = getchar())
            if (ch == '-') op = -1;
        for (; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    int main() {
        read(n);
        for (int i = 0; i < n; i++) read(f[i]);
        Poly :: ln(f, g, n);
        for (int i = 0; i < n; i++)
            printf("%lld%c", g[i], " 
    "[i == n - 1]);
        return 0;
    }
    View Code
  • 相关阅读:
    vector<vector<int>> 判断三个数为一组是否重复
    数位dp——hdu2089不要62
    nyoj1099 四点坐标判断正方形
    构造回文——最长公共子序列问题 java
    nyoj08 一种排序
    记录一个protobuf枚举类型引发问题的分析和思考
    记录一下996.icu
    Android N requires the IDE to be running with Java 1.8 or later
    使用fresco后引发的关于造轮子的思考
    使用了一段时间的instant run 记录一下遇到的问题
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/10277129.html
Copyright © 2011-2022 走看看