zoukankan      html  css  js  c++  java
  • 多项式 ln

    知识前备

    首先有复合函数的求导公式:G(x) = F(A(x)) → G'(x) = F'(A(x))A'(x)。

    ln 函数的导数:

    [ln'(x) = lim_{delta o 0} frac{ln(x+delta) - ln(x)}{delta} ]

    显然由于 ({ m e}^{ln(x+delta) - ln(x)} = dfrac{x + delta}x), 那么, (ln(x+delta) - ln(x) = ln(dfrac{x+delta}x)), 于是就有:

    [ln'(x) = lim_{delta o 0} frac{ln(1+dfrac{delta}x)}delta \ ]

    有个通过洛必达法则得出的结论,我没时间学,只好记了, 那就是 t 趋于 0 的时候, ln(1 + t) 趋近于 t。

    那么上式就是:(lim_{delta o 0} dfrac{dfrac{delta}x}delta = dfrac 1x)

    因此 ln 函数的导函数是 (dfrac 1x)


    本题

    给定多项式 A(x), 要求求多项式 B(x) 满足 B(x) ≡ ln(A(x)) mod xn

    [egin{align} ln A(x) &equiv B(x) mod x^n \ (ln A(x))' &equiv B(x)' mod x^n \ ln'(A(x))A(x)' &equiv B(x)' mod x^n \ frac {A(x)'}{A(x)} &equiv B(x)' mod x^n end{align} ]

    于是求导后积分即可。

    多项式求导:axn 的导函数 anxn-1, 常数项灭亡。

    void Dervt(int *a, int *b, int n) {
    	for(int i = 0; i < n - 1; ++i) b[i] = (LL)a[i + 1] * (i + 1) % mo;
    	b[n - 1] = 0;
    }
    

    多项式积分,准确的说是不定积分:axn 的反导函数是 axn+1/(n+1)。

    void Integ(int *a, int *b, int n) {
    	for(int i = 1; i < n; ++i) b[i] = (LL)a[i - 1] * Inv(i) % mo;
    	b[0] = 0;
    }
    

    容我复习下求逆。

    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;
    }
    

    #include<bits/stdc++.h>
    typedef long long LL;
    using namespace std;
    
    #define int long long
    
    const int N = 3e5 + 233, mo = 998244353;
    int ksm(int a, int b) {
    	int res = 1;
    	for(; b; b = b>>1, a = ((LL)a * a) % mo)
    		if(b & 1) res = ((LL)res * a) % mo;
    	return res % mo;
    }
    const int g = 3, ig = ksm(g, mo - 2);
    
    void Dervt(int n, int *a, int *b) {
    	for(int i = 0; i < n - 1; ++i) b[i] = (LL)a[i + 1] * (i + 1ll) % mo;
    	b[n - 1] = 0;
    }
    
    void Integ(int n, int *a, int *b) {
    	for(int i = 1; i < n; ++i) b[i] = (LL)a[i - 1] * ksm(i, mo - 2) % mo;
    	b[0] = 0;
    }
    
    int rv[N], t[N], n;
    void NTT(int *a, int n, int type) {
    	for(int i = 0; i < n; ++i) if(i < rv[i]) swap(a[i], a[rv[i]]);
    	for(int m = 2; m <= n; m = m << 1) {
    		int w = ksm(type == 1 ? g : ig, (mo - 1) / m);
    		for(int i = 0; i < n; i += m) {
    			int tmp = 1;
    			for(int j = 0; j < (m >> 1); ++j) {
    				int p = a[i + j] % mo, q = (LL)tmp * a[i + j + (m >> 1)] % mo;
    				a[i + j] = (p + q) % mo, a[i + j + (m >> 1)] = (p - q + mo) % mo;
    				tmp = (LL)tmp * w % mo;
    			}
    		}
    	}
    	if(type == -1) {
    		int Inv = ksm(n, mo - 2);
    		for(int i = 0; i < n; ++i) a[i] = (LL)a[i] * Inv % mo;
    	}
    }
    
    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) t[i] = a[i];
    	for(int i = deg; i < len; ++i) t[i] = 0;
    	for(int i = 1; i < len; ++i) rv[i] = (rv[i>>1]>>1) | (i&1 ? len>>1 : 0);
    	NTT(b, len, 1), NTT(t, len, 1);
    	for(int i = 0; i < len; ++i) b[i] = (LL)b[i] * (2ll - (LL)t[i] * b[i] % mo) % mo;
    	NTT(b, len, -1);
    	for(int i = deg; i < len; ++i) b[i] = 0;
    }
    
    int b[N], c[N];
    void poly_ln(int *a, int n) {
    	poly_inv(n, a, b), Dervt(n, a, c);
    	int len = 1; while(len < (n << 1)) len = len << 1;
    	for(int i = n; i < len; ++i) b[i] = c[i] = 0;
    	for(int i = 1; i < len; ++i) rv[i] = (rv[i >> 1] >> 1) | (i & 1 ? len >> 1 : 0);
    	NTT(b, len, 1), NTT(c, len, 1);
    	for(int i = 0; i < len; ++i) b[i] = (LL)b[i] * c[i] % mo;
    	NTT(b, len, -1);
    	Integ(n, b, a);
    }
    
    int a[N]; 
    
    signed main() {
    	scanf("%d", &n);
    	for(int i = 0; i < n; ++i) scanf("%lld", &a[i]), a[i] %= mo;
    	poly_ln(a, n);
    	for(int i = 0; i < n; ++i) cout << (a[i] + mo) % mo << ' ';
    	return 0;
    }
    
  • 相关阅读:
    366. Find Leaves of Binary Tree输出层数相同的叶子节点
    716. Max Stack实现一个最大stack
    515. Find Largest Value in Each Tree Row查找一行中的最大值
    364. Nested List Weight Sum II 大小反向的括号加权求和
    156. Binary Tree Upside Down反转二叉树
    698. Partition to K Equal Sum Subsets 数组分成和相同的k组
    244. Shortest Word Distance II 实现数组中的最短距离单词
    187. Repeated DNA Sequences重复的DNA子串序列
    java之hibernate之基于主键的双向一对一关联映射
    java之hibernate之基于主键的单向一对一关联映射
  • 原文地址:https://www.cnblogs.com/tztqwq/p/14327850.html
Copyright © 2011-2022 走看看