• 多项式 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;
    }
    
  • 相关阅读:
    2017-2018-1 20155334第八周课堂实践总结+课下作业+教材内容总结
    移动手机号段区别
    使用Maven搭建Hadoop开发环境
    RunMR.java
    BeanUtils内省工具包
    eclipse和myeclipse中如何关闭自动补全括号,花括号,双引号等功能
    为什么在jsp中写${pageContext.request.contextPath }失效了
    开发WEB项目的步骤
    MVC的职责分工
    关于import中使用*号是否会影响程序性能
  • 原文地址:https://www.cnblogs.com/tztqwq/p/14327850.html
Copyright © 2020-2023  润新知