luoguP4512 【模板】多项式除法 NTT+多项式求逆+多项式除法

Code:

#include<bits/stdc++.h>
#define maxn 300000
#define ll long long
#define MOD 998244353
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)
using namespace std;
namespace poly{
    #define P 998244352
    #define G 3
    int rev[maxn];
    ll X[maxn],Y[maxn];
    void calrev(int lim,int l){ for(int i=1;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));  }
    ll add(ll a,ll b){ return ((a+=b)%=MOD); }
    ll qpow(ll a,ll k){
        ll base=1;
        for(;k;a=(a*a)%MOD,k>>=1) if(k&1)base=(base*a)%MOD;
        return base;
    }
    void NTT(ll *a,int len,int opt){
        for(int i=0;i<len;++i) if(i<rev[i]) swap(a[i],a[rev[i]]);
        for(int i=1;i<len;i<<=1){
            int step=i<<1;
            ll wn=qpow(G,(opt*P/step+P));
            for(int j=0;j<len;j+=step){
                ll w=1;
                for(int k=0;k<i;++k,w=(1ll*w*wn)%MOD){
                    ll x=a[j+k];
                    ll y=1ll*w*a[j+k+i]%MOD;
                    a[j+k]=(x+y)%MOD;
                    a[j+k+i]=(x-y+MOD)%MOD;
                }
            }
        }
        if(opt==-1){
            ll r=qpow(len,MOD-2);
            for(int i=0;i<len;++i) a[i]=1ll*a[i]*r%MOD;
        }
    }
    void mul(ll *x,ll *y,int lim){
        memset(X,0,sizeof(X)),memset(Y,0,sizeof(Y));
        for(int i=0;i<(lim>>1);++i) X[i]=x[i],Y[i]=y[i];
        NTT(X,lim,1),NTT(Y,lim,1);
        for(int i=0;i<lim;++i) X[i]=(ll)X[i]*Y[i]%MOD;
        NTT(X,lim,-1);
        for(int i=0;i<lim;++i) x[i]=X[i];
    }
    ll B[3][maxn],C[maxn],D[maxn];
    void get_inv(int n,ll *A){
        int cur=0,bas=1,lim=2,len=1;
        B[cur][0]=qpow(A[0],MOD-2);
        calrev(lim,len);
        while(bas<=(n<<1)){
            cur^=1;
            memset(B[cur],0,sizeof(B[cur]));
            for(int i=0;i<bas;++i) B[cur][i]=add(B[cur^1][i]<<1,0);
            mul(B[cur^1],B[cur^1],lim),mul(B[cur^1],A,lim);
            for(int i=0;i<bas;++i) B[cur][i]=add(B[cur][i],MOD-B[cur^1][i]);
            bas<<=1,lim<<=1,++len;
            if(bas<=(n<<1)) calrev(lim,len);
        }
        for(int i=0;i<=n;++i) A[i]=B[cur][i];
    }
};
ll A[maxn],B[maxn],n,m,lim,len;
ll Ar[maxn],Br[maxn],Dr[maxn];
int main(){
    //setIO("input");
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;++i) scanf("%d",&A[i]),Ar[i]=A[i];
    for(int i=0;i<=m;++i) scanf("%d",&B[i]),Br[i]=B[i];
    reverse(Ar,Ar+n+1),reverse(Br,Br+m+1);
    for(int i=n-m+2;i<=max(n,m);++i) Br[i]=Ar[i]=0;
    poly::get_inv(n-m+1,Br);       //Br的逆
    lim=1,len=0;
    while(lim<=n-m+1+n-m+1) lim<<=1,++len;
    poly::calrev(lim,len), poly::mul(Ar,Br,lim);
    for(int i=n-m;i>=0;--i) printf("%lld ",Ar[i]),Dr[n-m-i]=Ar[i];       

    lim=1,len=0;
    while(lim<=n*2) lim<<=1,++len;
    poly::calrev(lim,len),poly::mul(B,Dr,lim);
    printf("\n");
    for(int i=0;i<=m-1;++i) {
        ll h=(A[i]-B[i]+MOD)%MOD;
        printf("%lld ",h);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/10739668.html

时间: 2024-11-02 21:38:13

luoguP4512 【模板】多项式除法 NTT+多项式求逆+多项式除法的相关文章

NTT+多项式求逆+多项式开方(BZOJ3625)

定义多项式h(x)的每一项系数hi,为i在c[1]~c[n]中的出现次数. 定义多项式f(x)的每一项系数fi,为权值为i的方案数. 通过简单的分析我们可以发现:f(x)=2/(sqrt(1-4h(x))+1) 于是我们需要多项式开方和多项式求逆. 多项式求逆: 求B(x),使得A(x)*B(x)=1 (mod x^m) 考虑倍增. 假设我们已知A(x)*B(x)=1 (mod x^m),要求C(x),使得A(x)*C(x)=1 (mod x^(2m)) 简单分析可得C(x)=B(x)*(2-A

[Codeforces438E][bzoj3625] 小朋友和二叉树 [多项式求逆+多项式开根]

题面 传送门 思路 首先,我们把这个输入的点的生成函数搞出来: \(C=\sum_{i=0}^{lim}s_ix^i\) 其中\(lim\)为集合里面出现过的最大的数,\(s_i\)表示大小为\(i\)的数是否出现过 我们再设另外一个函数\(F\),定义\(F_k\)表示总权值为\(k\)的二叉树个数 那么,一个二叉树显然可以通过两个子树(可以权值为0,也就是空子树)和一个节点构成 那么有如下求\(F\)的式子 \(F_0=1\) \(F_k=\sum_{i=0}^k s_i \sum_{j=0

[BZOJ3456]城市规划(生成函数+多项式求逆+多项式求ln)

城市规划 时间限制:40s      空间限制:256MB 题目描述 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了.  刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一样, 那么这两个方案就是不同的, 否则就是相同的. 现在你需要求出一共有多少不同的方案.  好了, 这就

BZOJ 3625 多项式求逆+多项式开根

思路: RT //By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=1<<18,mod=998244353; int A[N],C[N],invC[N],c[N],d[N],R[N],tmp[N],xx,len,sqrA[N],F[N]; typedef long long ll; int power(ll x,int y){ ll res=1; while(y){ if(y&1)r

【知识总结】多项式全家桶(一)(NTT、加减乘除和求逆)

我这种数学一窍不通的菜鸡终于开始学多项式全家桶了-- 必须要会的前置技能:FFT(不会?戳我:[知识总结]快速傅里叶变换(FFT)) 一.NTT 跟FFT功能差不多,只是把复数域变成了模域(计算复数系数多项式相乘变成计算在模意义下整数系数多项式相乘).你看FFT里的单位圆是循环的,模一个质数也是循环的嘛qwq.\(n\)次单位根\(w_n\)怎么搞?看这里:[BZOJ3328]PYXFIB(数学)(内含相关证明.只看与原根和单位根相关的内容即可.) 注意裸的NTT要求模数\(p\)存在原根并且\

luogu P4725 多项式对数函数 (模板题、FFT、多项式求逆、求导和积分)

手动博客搬家: 本文发表于20181125 13:25:03, 原地址https://blog.csdn.net/suncongbo/article/details/84487306 题目链接: https://www.luogu.org/problemnew/show/P4725 题目大意: 给定一个\(n\)次多项式\(A(x)\), 求一个\(n\)次多项式\(B(x)\)满足\(B(x)\equiv \ln A(x) (\mod x^n)\) 题解: 神数学模板题-- 数学真奇妙! 前驱

多项式FFT/NTT模板(含乘法/逆元/log/exp/求导/积分/快速幂)

自己整理出来的模板 存在的问题: 1.多项式求逆常数过大(尤其是浮点数FFT) 2.log只支持f[0]=1的情况,exp只支持f[0]=0的情况 有待进一步修改和完善 FFT: 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef double db; 5 const db pi=acos(-1); 6 const int N=4e5+10,M=1e6+10,mod=9982443

【BZOJ 3456】 3456: 城市规划 (NTT+多项式求逆)

3456: 城市规划 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 658  Solved: 364 Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一

【BZOJ】4555: [Tjoi2016&amp;Heoi2016]求和 排列组合+多项式求逆 或 斯特林数+NTT

[题意]给定n,求Σi=0~nΣj=1~i s(i,j)*2^j*j!,n<=10^5. [算法]生成函数+排列组合+多项式求逆 [题解]参考: [BZOJ4555][Tjoi2016&Heoi2016]求和-NTT-多项式求逆 $ans=\sum_{i=0}^{n}\sum_{j=0}^{i}s(i,j)*2^j*j!$ 令$g(n)=\sum_{j=0}^{n}s(n,j)*2^j*j!$ 则ans是Σg(i),只要计算出g(i)的生成函数就可以统计答案. g(n)可以理解为将n个数划分