多项式除法板子

借鉴了OBlack大神的模版
见于NKOJ3215

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
const int Q=500000,MOD=998244353;
inline int add(int a,int b)
{a+=b;return a<MOD?a:a-MOD;}
inline int sub(int a,int b)
{a-=b;return a<0?a+MOD:a;}
inline int ch(int a,int b)
{return 1LL*a*b%MOD;}
inline int ksm(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b&1)ans=ch(ans,a);
        b>>=1,a=ch(a,a);
    }
    return ans;
}
int w[Q];
void NTT(int a[],int n,int f)
{
    register int i,j,k,m,cnt=1;
    for(i=j=0;i<n;i++)
    {
        if(i<j)swap(a[i],a[j]);
        for(k=n>>1;(j^=k)<k;k>>=1);
    }
    w[0]=1;
    for(m=1;m<n;m<<=1,++cnt){
        int _now=ksm(3,(f*((MOD-1)>>cnt)+MOD-1)%(MOD-1));
        for(i=1;i<m;i++)w[i]=ch(w[i-1],_now);
        for(i=0;i<n;i+=(m<<1))
            for(j=0;j<m;j++){
                int p=a[i+j],q=ch(a[i+j+m],w[j]);
                a[i+j]=add(p,q),a[i+j+m]=sub(p,q);
            }
    }
    if(f<0){
        int n_ni=ksm(n,MOD-2);
        for(i=0;i<n;i++)a[i]=ch(a[i],n_ni);
    }
}
int it[Q];
void GetInv(int a[],int ni[],int toap) 
{ 
    int i,now; 
    ni[0]=ksm(a[0],MOD-2); 
    for(now=2;now<=toap;now<<=1){ 
        fill(ni+(now>>1),ni+(now<<1),0); 
        copy(a,a+now,it); 
        fill(it+now,it+(now<<1),0); 
        NTT(ni,now<<1,1); 
        NTT(it,now<<1,1); 
        for(i=0;i<(now<<1);i++) 
            ni[i]=ch(ni[i],sub(2,ch(it[i],ni[i]))); 
        NTT(ni,now<<1,-1); 
    } 
} 
int a[Q],b[Q],c[Q],r[Q],b_ni[Q];
int main()
{
    int p,q,i,now;
    scanf("%d%d",&p,&q);
    for(i=0;i<=p;i++)scanf("%d",&a[i]);
    for(i=0;i<=q;i++)scanf("%d",&b[i]);
    reverse(a,a+p+1),reverse(b,b+q+1);
    for(now=1;now<=p-q+1;now<<=1);
    GetInv(b,b_ni,now);
    fill(b_ni+now,b_ni+(now<<1),0);
    copy(a,a+now,c);
    fill(c+now,c+(now<<1),0);
    NTT(c,now<<1,1),NTT(b_ni,now<<1,1);
    for(int i=0;i<(now<<1);i++)c[i]=ch(c[i],b_ni[i]);
    NTT(c,now<<1,-1);
    fill(c+p-q+1,c+(now<<1),0);
    reverse(a,a+p+1);reverse(b,b+q+1);reverse(c,c+p-q+1);
    for(i=0;i<=p-q;i++)printf("%d ",c[i]);
    putchar('\n');
    for(now=1;now<=p;now<<=1);
    NTT(c,now,1),NTT(b,now,1),NTT(a,now,1);
    for(i=0;i<now;i++)r[i]=sub(a[i],ch(b[i],c[i]));
    NTT(r,now,-1);
    for(i=0;i<q;i++)printf("%d ",r[i]);
    //NTT(a,now,-1),NTT(b,now,-1),NTT(c,now,-1);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值