zoukankan      html  css  js  c++  java
  • 多项式求逆。。跟着学长一起学的,没怎么看懂

    只会照着板打的蒟蒻。。

    多项式求逆,详见: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);
    }
  • 相关阅读:
    测试签名和验证签名
    自定义mssql的CLR函数
    关于C#的Process的内存相关属性解读
    测试C#发送邮件
    关于wmv视频格式
    练习命名管道的使用
    web中局部滚动条
    C#修改文件的安全属性时报“没有可以设置的标志”
    c#的FileSystemWatcher对象监视文件的变化的事件,无休止的触发事件的解决办法
    为什么要给自己设限?
  • 原文地址:https://www.cnblogs.com/chenjingqi/p/8969483.html
Copyright © 2011-2022 走看看