自己码了一个模板...有点辛苦...常数十分大,小心使用

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <algorithm>
#include <vector>
using namespace std;
#define ll long long
#define pb push_back
ll MOD=;
#define SZ 666666
ll w[][SZ];
ll qp(ll a,ll b)
{
    ll ans=;
    while(b)
    {
        ) ans=ans*a%MOD;
        a=a*a%MOD; b>>=;
    }
    return ans;
}
int K;
void fftinit(int n)
{
    ;K<n;K<<=);
    w[][]=w[][K]=;
    ll g=qp(,(MOD-)/K); //3是原根
    ;i<K;i++) w[][i]=w[][i-]*g%MOD;
    ;i<=K;i++) w[][i]=w[][K-i];
}
void fft(int* x,int v)
{
    ,j=;i<K;i++)
    {
        if(i>j) {x[i]^=x[j]; x[j]^=x[i]; x[i]^=x[j];}
        ;(j^=l)<l;l>>=);
    }
    ;i<=K;i<<=)
    {
        ;j<K;j+=i)
        {
            ;l<i>>;l++)
            {
                ll t=(ll)x[j+l+(i>>)]*w[v][K/i*l]%MOD;
                x[j+l+(i>>)]=(x[j+l]-t+MOD)%MOD;
                x[j+l]=(x[j+l]+t)%MOD;
            }
        }
    }
    if(!v) return;
    ll rv=qp(K,MOD-);
    ;i<K;i++) x[i]=x[i]*rv%MOD;
}
struct poly
{
    vector<int> ps;
    ;}
    int& operator [] (int x) {return ps[x];} //ps.at(x)
    );}
    void dbg()
    {
        ;
        ;i--)
        {
            if(!ps[i]) continue;
            if(fi)
            {
                ) printf("+%d",ps[i]);
                ) printf("+");
                ) printf("-");
                else printf("+%d",ps[i]);
            }
            else
            {
                ) printf("%d",ps[i]);
                );
                ) printf("-");
                else printf("%d",ps[i]);
            }
            ) printf("x^%d",i);
            ) printf("x");
            fi=;
        }
        ");
        putchar();
    }
    void clr()
    {
        ;
        ]) --p;
        sc(p-);
    }
};
ll gm(ll x)
{
    x=x%MOD;
    ) x+=MOD;
    return x;
}
namespace PolyMul{int ta[SZ],tb[SZ],tc[SZ];}
poly operator * (poly a,poly b)
{
    using namespace PolyMul;
    ||b.cs()<)
    {
        poly g;
        g.sc(a.cs()+b.cs());
        ;i<=a.cs();i++)
        {
            ;j<=b.cs();j++) g[i+j]=gm(g[i+j]+a[i]*(ll)b[j]%MOD);
        }
        return g;
    }
    poly c;
    int t=a.cs()+b.cs();
    c.sc(t); fftinit(t+);
    memset(ta,,sizeof(int)*K);
    memset(tb,,sizeof(int)*K);
    memset(tc,,sizeof(int)*K);
    ;i--) ta[i]=a[i];
    ;i--) tb[i]=b[i];
    fft(ta,); fft(tb,);
    ;i<K;i++) tc[i]=(ll)ta[i]*tb[i]%MOD;
    fft(tc,);
    ;i--) c[i]=tc[i];
    c.clr();
    return c;
}
namespace PolyInv{int ay[SZ],a0[SZ],tmp[SZ];}
void ginv(int t)
{
    using namespace PolyInv;
    ) {a0[]=qp(ay[],MOD-); return;}
    ginv((t+)>>); fftinit(t+t+);
    memset(tmp,,sizeof(int)*K);
    ;
    ;i<t;i++) tmp[i]=ay[i];
    fft(tmp,); fft(a0,);
    ;i<K;i++) a0[i]=gm((-(ll)tmp[i]*a0[i])%MOD*a0[i]);
    fft(a0,);
    ;
}
poly inv(poly x)
{
    using namespace PolyInv;
    poly y; y.sc(x.cs());
    ;i--) ay[i]=x[i];
    ginv(x.cs()+);
    ;i--) y[i]=a0[i];
    y.clr();
    return y;
}
poly operator + (poly a,poly b)
{
    poly w; w.sc(max(a.cs(),b.cs()));
    ;i--) w[i]=a[i];
    ;i--) w[i]+=b[i], w[i]=gm(w[i]);
    return w;
}
poly operator - (poly a,poly b)
{
    poly w; w.sc(max(a.cs(),b.cs()));
    ;i--) w[i]=a[i];
    ;i--) w[i]-=b[i], w[i]=gm(w[i]);
    w.clr();
    return w;
}
void div(poly a,poly b,poly& d,poly& r)
{
    int n=a.cs(),m=b.cs();
    ); d[]=; r=a; return;}
    fftinit(*n);
    poly aa=a; reverse(aa.ps.begin(),aa.ps.end());
    poly bb=b; reverse(bb.ps.begin(),bb.ps.end());
    bb.sc(n-m); bb=inv(bb); d=aa*bb; d.sc(n-m);
    reverse(d.ps.begin(),d.ps.end()); r=a-b*d;
    r.clr();
}
poly operator / (poly a,poly b)
{
    poly d,r; div(a,b,d,r); return d;
}
poly operator % (poly a,poly b)
{
    poly d,r; div(a,b,d,r); return r;
}
poly dev(poly x)
{
    ;i<=x.cs();i++) x[i-]=(ll)x[i]*i%MOD;
    x.sc(x.cs()-); return x;
}
poly inte(poly x) //C=0
{
    x.sc(x.cs()+);
    ;i--) x[i]=x[i-]; x[]=;
    ;i--) x[i]=(ll)x[i]*qp(i,MOD-)%MOD;
    return x;
}
ll qz_(poly& a,ll x)
{
    ll ans=;
    ;i--) ans=(ans*x%MOD+a[i])%MOD;
    return gm(ans);
}
namespace PolyGetv{int xs[SZ],anss[SZ];};
void gv(poly f,int m,int* x,int* ans)
{
    //f.clr();
    )
    {
        ;i<=m;i++) ans[i]=qz_(f,x[i]);
        return;
    }
    poly m0,m1,tmp;
    m0.sc(); m1.sc(); tmp.sc();
    m0[]=m1[]=; tmp[]=;
    ;
    ;i<=hf;i++) tmp[]=gm(-x[i]), m0=m0*tmp;
    ;i<=m;i++) tmp[]=gm(-x[i]), m1=m1*tmp;
    gv(f%m0,hf,x,ans);
    gv(f%m1,m-hf,x+hf+,ans+hf+);
}
vector<int> getv(poly a,vector<int> x)
{
    using namespace PolyGetv;
    a.clr();
    if(!x.size()) return vector<int>();
    ;
    ;i<=m;i++) xs[i]=x[i];
    gv(a,m,xs,anss);
    vector<);
    ;i<=m;i++) ans[i]=anss[i];
    return ans;
}
int main()
{
}

加减乘逆元除取模求导积分多点求值...感觉够用了。

大部分运算没有用题目测试过...都是小数据/目测啥的...有问题求评论告知。

相关介绍请见picks博客及上一篇FFT入门。

http://picks.logdown.com/posts/177631-fast-fourier-transform

http://picks.logdown.com/posts/189620-inverse-element-of-polynomial

http://picks.logdown.com/posts/197262-polynomial-division

http://www.cnblogs.com/zzqsblog/p/5665654.html

05-04 09:46