多项式求逆。。跟着学长一起学的,没怎么看懂

只会照着板打的蒟蒻。。

多项式求逆,详见:http://blog.miskcoo.com/2015/05/polynomial-inverse

下面是道板题(据说),题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=1952

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#define P 1004535809
#define ll long long
#define maxn 400005
using namespace std;
ll n,h[maxn],g[maxn],ans[maxn],inv_tmp[maxn],jc[maxn];
ll rev[maxn],dig[maxn],fac[maxn];
ll add(ll a,ll b) {
    a+=b;
    return a>=P?a-P:a;
}
ll sub(ll a,ll b) {
    a-=b;
    return a<0?a+P:a;
}
ll mul(ll a,ll b) {
    return a*b%P;
}
ll ksm(ll a,ll b) {
    ll ans=1;
    while(b) {
        if(b&1)ans=(ans*a)%P;
        a=(a*a)%P;
        b>>=1;
    }
    return ans;
}
void NTT(ll *p,ll n,ll tt) {
    ll i,j,k,m;
    ll t0,t1,aa,bb;
    for(i=0; i<n; ++i) {
        for(j=0,k=i,m=n-1;m>0;j=(j<<1)|(k&1),k>>=1,m>>=1);
        if(i<j)swap(p[i],p[j]);//cout<<rev[i]<<"==========="<<endl;
    }
    for(m=1; m<n; m<<=1) {
        aa=ksm(3,(P-1+tt*(P-1)/(m<<1))%(P-1));
        for(i=0; i<n; i+=(m<<1)) {
            bb=1;
            for(j=0; j<m; ++j) {
                t0=p[i+j];
                t1=mul(p[i+j+m],bb);
                //cout<<i+j<<"-"<<t0<<"-"<<i+j+m<<"-"<<t1<<endl;
                p[i+j]=add(t0,t1);
                p[i+j+m]=sub(t0,t1);
                bb=mul(bb,aa);
            }
        }
    }
    //cout<<"                  "<<endl;
    if(tt==-1) {
        t0=ksm(n,P-2);
        for(i=0; i<n; ++i) {
            p[i]=mul(p[i],t0);
        }
    }
}
void poly_inv(ll *a,ll *b,ll n) {
    if(n==1) {
        b[0]=ksm(a[0],P-2);
        return;
    }
    poly_inv(a,b,(n+1)>>1);
    ll N=1;
    while(N<=n)N<<=1;
    N<<=1;
    for (ll i=0; i<=n; ++i) inv_tmp[i]=a[i];//,cout<<a[i]<<"---------"<<endl;
    for (ll i=n+1; i<N; ++i) inv_tmp[i]=0;
    NTT(inv_tmp,N,1);
    NTT(b,N,1);
    for (ll i=0; i<N; ++i) inv_tmp[i]=b[i]*(2-1*inv_tmp[i]*b[i]%P+P)%P;
    NTT(inv_tmp,N,-1);
    for (ll i=0; i<=n; ++i) b[i]=inv_tmp[i];
    for (ll i=n+1; i<N; ++i) b[i]=0;
}
void poly_mul(ll *a,ll *b,ll n) {
    ll N=1;
    while(N<=n)N<<=1;
    N<<=1;
    for (ll i=n+1; i<N; ++i) a[i]=b[i]=0;
    NTT(a,N,1);
    NTT(b,N,1);
    for (ll i=0; i<N; ++i) a[i]=1ll*a[i]*b[i]%P;
    NTT(a,N,-1);
}
int main() {
    scanf("%lld",&n);
    h[0]=1;
    ll k=1,L=0;
    while(k<=2*n) {
        k<<=1;
        L++;
    }
    for (ll i=1; i<=n; ++i) h[i]=ksm(2,i*(i-1)/2);
    jc[0]=1;
    for(ll i=1; i<=n; ++i)jc[i]=jc[i-1]*i%P;
    for (ll i=0; i<=n; ++i)fac[i]=ksm(jc[i],P-2);
    for (ll i=1; i<=n; ++i)g[i]=h[i]*fac[i-1]%P;
    for (ll i=0; i<=n; ++i)h[i]=h[i]*fac[i]%P;
    poly_inv(h,ans,n+1);
    poly_mul(ans,g,n);
    printf("%lld",(ans[n]*jc[n-1]%P+P)%P);
}

猜你喜欢

转载自www.cnblogs.com/chenjingqi/p/8969483.html