[学习笔记] 多项式求逆、带余除法、取模、求对数、求指数

一晚上写完求逆取模求ln求exp真酸爽
明天再顺手把求值插值写了人生就圆满了
求逆:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define gc getchar()
#define lint long long
#define p 998244353
#define N 1600010
#define clr(a,n) memset(a,0,sizeof(int)*(n))
#define cpy(a,b,n) memcpy(a,b,sizeof(int)*(n))
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline int fast_pow(int x,int k,int ans=1)
{	for(;k;k>>=1,x=(lint)x*x%p) (k&1)?ans=(lint)ans*x%p:0;return ans; }
int a[N],b[N],f[N],g[N],h[N],r[N];
inline int NTT(int *a,int n,int s,int L=0)
{
    for(int i=1;i<n;i++) if(i<r[i]) swap(a[i],a[r[i]]);
    for(int i=2;i<=n;i<<=1)
    {
        int wn=fast_pow(3,(s>0)?(p-1)/i:p-1-(p-1)/i);
        for(int j=0,t=i>>1;j<n;j+=i)
            for(int k=0,w=1;k<t;k++,w=(lint)w*wn%p)
            {
                int x=a[j+k],y=(lint)w*a[j+k+t]%p;
                a[j+k]=(x+y)%p,a[j+k+t]=(x-y+p)%p;
            }
    }
    int ninv=fast_pow(n,p-2);
    if(s<0) for(int i=0;i<n;i++) a[i]=(lint)a[i]*ninv%p;
    return 0;
}
inline int tms(int *A,int *B,int *C,int m)//C=AB
{
    int n=1,L=0;for(;n<=2*m;n<<=1,L++);
    for(int i=1;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));
    cpy(a,A,m),cpy(b,B,m),clr(a+m,n-m),clr(b+m,n-m);
    NTT(a,n,1),NTT(b,n,1);
    for(int i=0;i<n;i++) C[i]=(lint)a[i]*b[i]%p;
    return NTT(C,n,-1);
}
inline int polyinv(int *f,int *g,int n,int m=1)
{
    for(;m<=n;m<<=1);
    clr(g,n=m),g[0]=fast_pow(f[0],p-2);
    for(int i=2;i<=n;i<<=1)
    {
        cpy(h,g,i);
        for(int j=0;j<i;j++) h[j]=2ll*h[j]%p;
        tms(g,g,g,i>>1),tms(f,g,g,i);//ke yi you hua
        for(int j=0;j<i;j++) g[j]=(h[j]-g[j]+p)%p;
        clr(g+i,i);
    }
    return 0;
}
int main()
{
    int n=inn();
    for(int i=0;i<n;i++) f[i]=inn();
    polyinv(f,g,n);
    for(int i=0;i<n;i++) printf("%d ",g[i]);
    return !printf("\n");
}

除法/取模

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define gc getchar()
#define lint long long
#define p 998244353
#define N 800010
#define clr(a,n) memset(a,0,sizeof(int)*(n))
#define cpy(a,b,n) memcpy(a,b,sizeof(int)*(n))
#define rev(a,n) for(int i=0;i<=(n)/2;i++) swap(a[i],a[(n)-i])
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline int fast_pow(int x,int k,int ans=1)
{	for(;k;k>>=1,x=(lint)x*x%p) (k&1)?ans=(lint)ans*x%p:0;return ans; }
int a[N],b[N],f[N],g[N],h[N],r[N],t[N],gs[N];
inline int NTT(int *a,int n,int s)
{
    for(int i=1;i<n;i++) if(i<r[i]) swap(a[i],a[r[i]]);
    for(int i=2;i<=n;i<<=1)
    {
        int wn=fast_pow(3,(s>0)?(p-1)/i:p-1-(p-1)/i);
        for(int j=0,t=i>>1;j<n;j+=i)
            for(int k=0,w=1;k<t;k++,w=(lint)w*wn%p)
            {
                int x=a[j+k],y=(lint)w*a[j+k+t]%p;
                a[j+k]=(x+y)%p,a[j+k+t]=(x-y+p)%p;
            }
    }
    int ninv=fast_pow(n,p-2);
    if(s<0) for(int i=0;i<n;i++) a[i]=(lint)a[i]*ninv%p;
    return 0;
}
inline int tms(int *A,int *B,int *C,int m1,int m2)//C=AB
{
    int n=1,L=0;for(;n<=m1+m2;n<<=1,L++);
    for(int i=1;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));
    cpy(a,A,m1),cpy(b,B,m2),clr(a+m1,n-m1),clr(b+m2,n-m2);
    NTT(a,n,1),NTT(b,n,1);
    for(int i=0;i<n;i++) C[i]=(lint)a[i]*b[i]%p;
    return NTT(C,n,-1);
}
inline int tms(int *A,int *B,int *C,int n) { return tms(A,B,C,n,n); }
inline int polyinv(int *f,int *g,int n,int m=1)
{
    for(;m<=n;m<<=1);
    clr(g,n=m),g[0]=fast_pow(f[0],p-2);
    for(int i=2;i<=n;i<<=1)
    {
        cpy(h,g,i);
        for(int j=0;j<i;j++) h[j]=2ll*h[j]%p;
        tms(g,g,g,i>>1),tms(f,g,g,i);
        for(int j=0;j<i;j++) g[j]=(h[j]-g[j]+p)%p;
        clr(g+i,i);
    }
    return 0;
}
int main()
{
    int n=inn(),m=inn();
    for(int i=0;i<=n;i++) f[i]=inn();
    for(int i=0;i<=m;i++) gs[i]=g[i]=inn();
    cpy(t,g,m+1);rev(t,m);rev(f,n);
    for(int i=n-m+2;i<=m;i++) t[i]=0;
    polyinv(t,g,n-m+1);tms(f,g,h,n-m+1,n-m+1);rev(h,n-m);
    for(int i=0;i<=n-m;i++) printf("%d ",h[i]);printf("\n");
    tms(h,gs,g,n-m+1,m+1);rev(f,n);
    for(int i=0;i<m;i++) printf("%d ",(f[i]-g[i]+p)%p);
    return !printf("\n");
}

求ln

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define gc getchar()
#define lint long long
#define p 998244353
#define N 800010
#define clr(a,n) memset(a,0,sizeof(int)*(n))
#define cpy(a,b,n) memcpy(a,b,sizeof(int)*(n))
#define rev(a,n) for(int i=0;i<=(n)/2;i++) swap(a[i],a[(n)-i])
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline int fast_pow(int x,int k,int ans=1)
{	for(;k;k>>=1,x=(lint)x*x%p) (k&1)?ans=(lint)ans*x%p:0;return ans; }
int a[N],b[N],f[N],g[N],h[N],r[N];
inline int NTT(int *a,int n,int s)
{
    for(int i=1;i<n;i++) if(i<r[i]) swap(a[i],a[r[i]]);
    for(int i=2;i<=n;i<<=1)
    {
        int wn=fast_pow(3,(s>0)?(p-1)/i:p-1-(p-1)/i);
        for(int j=0,t=i>>1;j<n;j+=i)
            for(int k=0,w=1;k<t;k++,w=(lint)w*wn%p)
            {
                int x=a[j+k],y=(lint)w*a[j+k+t]%p;
                a[j+k]=(x+y)%p,a[j+k+t]=(x-y+p)%p;
            }
    }
    int ninv=fast_pow(n,p-2);
    if(s<0) for(int i=0;i<n;i++) a[i]=(lint)a[i]*ninv%p;
    return 0;
}
inline int tms(int *A,int *B,int *C,int m1,int m2)//C=AB
{
    int n=1,L=0;for(;n<=m1+m2;n<<=1,L++);
    for(int i=1;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));
    cpy(a,A,m1),cpy(b,B,m2),clr(a+m1,n-m1),clr(b+m2,n-m2);
    NTT(a,n,1),NTT(b,n,1);
    for(int i=0;i<n;i++) C[i]=(lint)a[i]*b[i]%p;
    return NTT(C,n,-1);
}
inline int tms(int *A,int *B,int *C,int n) { return tms(A,B,C,n,n); }
inline int polyinv(int *f,int *g,int n,int m=1)
{
    for(;m<=n;m<<=1);
    clr(g,n=m),g[0]=fast_pow(f[0],p-2);
    for(int i=2;i<=n;i<<=1)
    {
        cpy(h,g,i);
        for(int j=0;j<i;j++) h[j]=2ll*h[j]%p;
        tms(g,g,g,i>>1),tms(f,g,g,i);
        for(int j=0;j<i;j++) g[j]=(h[j]-g[j]+p)%p;
        clr(g+i,i);
    }
    return 0;
}
inline int polydif(int *f,int *g,int n) { for(int i=0;i<n;i++) g[i]=f[i+1]*(i+1ll)%p;return 0; }
inline int polyint(int *f,int *g,int n) { g[0]=0;for(int i=1;i<=n;i++) g[i]=(lint)fast_pow(i,p-2)*f[i-1]%p;return 0; }
inline int polyln(int *f,int *g,int n)
{
    polyinv(f,g,n),polydif(f,h,n),tms(g,h,h,n),polyint(h,g,n);
    return 0;
}
int main()
{
    int n=inn();
    for(int i=0;i<n;i++) f[i]=inn();
    polyln(f,g,n);
    for(int i=0;i<n;i++) printf("%d ",g[i]);
    return !printf("\n");
}

求exp

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<assert.h>
#define gc getchar()
#define lint long long
#define p 998244353
#define N 2000010
#define clr(a,n) memset(a,0,sizeof(int)*(n))
#define cpy(a,b,n) memcpy(a,b,sizeof(int)*(n))
#define rev(a,n) for(int i=0;i<=(n)/2;i++) swap(a[i],a[(n)-i])
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
    int x,ch;while((ch=gc)<'0'||ch>'9');
    x=ch^'0';while((ch=gc)>='0'&&ch<='9')
        x=(x<<1)+(x<<3)+(ch^'0');return x;
}
inline int fast_pow(int x,int k,int ans=1)
{	for(;k;k>>=1,x=(lint)x*x%p) (k&1)?ans=(lint)ans*x%p:0;return ans; }
int a[N],b[N],f[N],g[N],h[N],r[N],t[N];
inline int NTT(int *a,int n,int s)
{
    for(int i=1;i<n;i++) if(i<r[i]) swap(a[i],a[r[i]]);
    for(int i=2;i<=n;i<<=1)
    {
        int wn=fast_pow(3,(s>0)?(p-1)/i:p-1-(p-1)/i);
        for(int j=0,t=i>>1;j<n;j+=i)
            for(int k=0,w=1;k<t;k++,w=(lint)w*wn%p)
            {
                int x=a[j+k],y=(lint)w*a[j+k+t]%p;
                a[j+k]=(x+y)%p,a[j+k+t]=(x-y+p)%p;
            }
    }
    int ninv=fast_pow(n,p-2);
    if(s<0) for(int i=0;i<n;i++) a[i]=(lint)a[i]*ninv%p;
    return 0;
}
inline int tms(int *A,int *B,int *C,int m1,int m2)//C=AB
{
    int n=1,L=0;for(;n<=m1+m2;n<<=1,L++);
    for(int i=1;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));
    cpy(a,A,m1),cpy(b,B,m2),clr(a+m1,n-m1),clr(b+m2,n-m2);
    NTT(a,n,1),NTT(b,n,1);
    for(int i=0;i<n;i++) C[i]=(lint)a[i]*b[i]%p;
    return NTT(C,n,-1);
}
inline int tms(int *A,int *B,int *C,int n) { return tms(A,B,C,n,n); }
inline int polyinv(int *f,int *g,int n,int m=1)
{
    for(;m<=n;m<<=1);clr(g,n=m),g[0]=fast_pow(f[0],p-2);
    for(int i=2;i<=n;i<<=1)
    {
        cpy(h,g,i);
        for(int j=0;j<i;j++) h[j]=2ll*h[j]%p;
        tms(g,g,g,i>>1),tms(f,g,g,i);
        for(int j=0;j<i;j++) g[j]=(h[j]-g[j]+p)%p;
        clr(g+i,i);
    }
    return 0;
}
inline int polydif(int *f,int *g,int n) { for(int i=0;i<n;i++) g[i]=f[i+1]*(i+1ll)%p;return 0; }
inline int polyint(int *f,int *g,int n) { g[0]=0;for(int i=1;i<=n;i++) g[i]=(lint)fast_pow(i,p-2)*f[i-1]%p;return 0; }
inline int polyln(int *f,int *g,int n) { return polyinv(f,g,n),polydif(f,h,n),tms(g,h,h,n),polyint(h,g,n); }
inline int polyexp(int *f,int *g,int n,int m=1)
{
    for(;m<=n*2;m<<=1);clr(g,n=m),g[0]=1;
    for(int i=2;i<=n;i<<=1)
    {
        polyln(g,t,i>>1);
        for(int j=0;j<(i>>1);j++) h[j]=(f[j]-t[j]+(j==0)+p)%p;
        tms(h,g,g,i>>1),clr(g+i,i);
    }
    return 0;
}
int main()
{
    int n=inn();
    for(int i=0;i<n;i++) f[i]=inn();
    polyexp(f,g,n);
    for(int i=0;i<n;i++) printf("%d ",g[i]);
    return !printf("\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值