zoukankan      html  css  js  c++  java
  • luogu4328 多项式求逆

    题目链接

    problem

    给出一个多项式f,求一个多项式g使得(f(x)*g(x) equiv 1 (mod x ^ n))

    solution

    利用倍增。假设现在我们已经求出了(f(x))(mod x ^ n)的逆元(g(x)),考虑如何求出在(mod x ^{2n})下的逆元(g'(x))

    [f(x)g(x)equiv 1 (mod x ^ n) \ f(x)g(x) - 1 equiv0(mod x ^ n) \ f^2(x)g^2(x)-2f(x)g(x) + 1equiv 0(mod x ^{2n}) \ 2f(x)g(x) - f^2(x)g^2(x) equiv 1 (mod x ^{2n})\ f(x)(2g(x)-f(x)g^2(x))equiv 1(mod x ^ {2n}) ]

    所以,f(x)在(mod x^{2n})下的逆元就是(2g(x)-f(x)g^2(x))。递归求解即可。注意NTT的时候每次翻转的范围都要重新计算。

    code

    /*
    * @Author: wxyww
    * @Date: 2020-01-28 09:39:19
    * @Last Modified time: 2020-01-28 11:46:14
    */
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<bitset>
    #include<cstring>
    #include<algorithm>
    #include<string>
    #include<queue>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int N = 400010,mod = 998244353;
    ll read() {
    	ll x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9') {
    		if(c=='-') f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9') {
    		x=x*10+c-'0';
    		c=getchar();
    	}
    	return x*f;
    }
    int qm(ll x,int y) {
    	ll ret = 1;
    	for(;y;y >>= 1,x = x * x % mod)
    		if(y & 1) ret = ret * x % mod;
    
    	return ret;
    }
    int rev[N];
    void NTT(ll *a,int n,int xs) {
    	
    		for(int i = 0;i <= n;++i) 
    		rev[i] = (rev[i >> 1] >> 1) | (i & 1 ? (n >> 1) : 0);
    
    	for(int i = 0;i <= n;++i)
    		if(rev[i] > i) swap(a[i],a[rev[i]]);
    	for(int m = 2;m <= n;m <<= 1) {
    		ll w1 = qm(3,(mod - 1) / m);
    		if(xs == -1) w1 = qm(w1,mod - 2);
    
    		for(int i = 0;i < n;i += m) {
    			ll w = 1;
    			for(int k = 0;k < (m >> 1);++k) {
    				ll u = a[i + k],t = w * a[i + k + (m >> 1)] % mod;
    				a[i + k] = (u + t) % mod;a[i + k + (m >> 1)] = (u - t) % mod;
    				w = w * w1 % mod;
    			}
    		}
    	}
    
    	if(xs == -1) {
    		for(int i = 0,inv = qm(n,mod - 2);i < n;++i) a[i] = a[i] * inv % mod;
    	}
    }
    ll A[N],B[N];
    void solve(ll *F,ll *G,ll len) {
    	if(len == 1) {
    		G[0] = qm(F[0],mod - 2);
    		return;
    	}
    	solve(F,G,len >> 1);
    	for(int i = 0;i < len;++i) A[i] = F[i],B[i] = G[i];
    	NTT(A,len << 1,1);NTT(B,len << 1,1);
    	for(int i = 0;i < (len << 1);++i) 
    		A[i] = 1ll * A[i] * B[i] % mod * B[i] % mod;
    	NTT(A,len << 1,-1);
    	for(int i = 0;i < len;++i) G[i] = (2ll * G[i] % mod - A[i]) % mod;
    }
    
    
    ll f[N],g[N];
    int main() {
    	int n = read() - 1;
    
    	for(int i = 0;i <= n;++i) f[i] = read();
    
    	int tot = 1;
    	while(tot <= n) tot <<= 1;
    
    	solve(f,g,tot);
    
    	for(int i = 0;i <= n;++i) printf("%d ",(g[i] + mod) % mod);
    	return 0;
    }
    
  • 相关阅读:
    ntohs, ntohl, htons,htonl的比较和详解
    转 linux socket的select函数例子
    转 结构体中字节对齐问题(转载)
    C语言中volatile关键字的作用
    转 字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法
    转 常见hash算法的原理
    转 从头到尾彻底解析Hash表算法
    [CEOI2020 D2T1 / CF1403A] 权力药水The Potion of Great Power 题解
    [CEOI2020 D1T3 / CF1402C] 星际迷航Star Trek 题解
    [CEOI2020 D1T2 / CF1402B] 道路Roads 题解
  • 原文地址:https://www.cnblogs.com/wxyww/p/luogu4238.html
Copyright © 2011-2022 走看看