zoukankan      html  css  js  c++  java
  • CF755G PolandBall and Many Other Balls

    PolandBall and Many Other Balls

    There are exactly \(n\) Balls

    Select exactly \(m\) groups of Balls, each consisting either of single Ball or two neighboring Balls. Each Ball can join no more than one group.

    Calculate number of such divisions for all \(m\) where \(1 ≤ m ≤ k\). Output all these values modulo \(998244353\)

    \(1 ≤ n ≤ 10^9, 1 ≤ k < 2^{15}\)

    题解

    https://blog.csdn.net/make_it_for_good/article/details/69943249

    CF的Tutorial给我一种“就是为了倍增我才出的这道题”的感觉。

    计数DP。\(f(i,j)\)表示前\(i\)个球分了\(j\)组的方案数。显然有

    \[\begin{equation} f(i,j)=f(i-1,j)+f(i-1,j-1)+f(i-2,j-1) \end{equation} \]

    写出生成函数。

    \[F_i=(x+1)F_{i-1}+xF_{i-2} \]

    二阶齐次线性递推,解特征方程\(y^2-(x+1)y-x=0\)

    \[\alpha=\frac{1+x+\sqrt{1+6x+x^2}}{2},\beta=\frac{1+x-\sqrt{1+6x+x^2}}{2} \]

    用待定系数法设\(F_n=A\alpha^n+B\beta^n\)(注意\(A,B\)也是多项式),代入\(F_0=1,F_1=1+x\)

    \[A=\frac{1+x+\sqrt{1+6x+x^2}}{2\sqrt{1+6x+x^2}},B=-\frac{1+x-\sqrt{1+6x+x^2}}{2\sqrt{1+6x+x^2}} \]

    所以有

    \[F_n=\frac{\left(\frac{1+x+\sqrt{1+6x+x^2}}{2}\right)^{n+1}-\left(\frac{1+x-\sqrt{1+6x+x^2}}{2}\right)^{n+1}}{\sqrt{1+6x+x^2}} \]

    因为\(1+x-\sqrt{1+6x+x^2}\)常数项是\(0\),所以第二个幂\(\bmod x^{n+1}=0\),可以不管。

    多项式操作,时间复杂度\(O(k2^k)\)

    多项式开根完全可以用多项式ln+exp代替。因为常数项是\(1\)所以不用写二次剩余。

    #include<bits/stdc++.h>
    using namespace std;
    using int64=long long;
    using poly=vector<int>;
    
    template<class T>
    T read(){
        T x=0; char w=1, c=getchar();
        for(; !isdigit(c); c=getchar())if(c=='-') w=-w;
        for(; isdigit(c); c=getchar()) x=x*10+c-'0';
        return x*w;
    }
    template<class T>
    T& read(T& x){
        return x=read<T>();
    }
    
    constexpr int mod=998244353;
    int add(int a, int b){
        return (a+=b)>=mod ? a-mod : a;
    }
    int mul(int a, int b){
        return (int64)a*b%mod;
    }
    int fpow(int a, int b){
        int ans=1;
        for(; b; b>>=1, a=mul(a, a))
            if(b&1) ans=mul(ans, a);
        return ans;
    }
    
    constexpr int N=1<<16;
    int omg[2][N], rev[N];
    int fac[N], inv[N], ifac[N];
    
    void init_NTT(){
        omg[0][0]=1, omg[0][1]=fpow(3, (mod-1)/N);
        omg[1][0]=1, omg[1][1]=fpow(omg[0][1], mod-2);
        rev[0]=0, rev[1]=1<<15;
        fac[0]=fac[1]=1;
        inv[0]=inv[1]=1;
        ifac[0]=ifac[1]=1;
        for(int i=2; i<N; ++i){
            omg[0][i]=mul(omg[0][i-1], omg[0][1]);
            omg[1][i]=mul(omg[1][i-1], omg[1][1]);
            rev[i]=rev[i>>1]>>1|(i&1)<<15;
            fac[i]=mul(fac[i-1], i);
            inv[i]=mul(mod-mod/i, inv[mod%i]);
            ifac[i]=mul(ifac[i-1], inv[i]);
        }
    }
    void NTT(poly& a, int dir){
        int lim=a.size(), len=log2(lim);
        for(int i=0; i<lim; ++i){
            int r=rev[i]>>(16-len);
            if(i<r) swap(a[i], a[r]);
        }
        for(int i=1; i<lim; i<<=1)
            for(int j=0; j<lim; j+=i<<1)for(int k=0; k<i; ++k){
                int t=mul(omg[dir][N/(i<<1)*k], a[j+i+k]);
                a[j+i+k]=add(a[j+k], mod-t), a[j+k]=add(a[j+k],t);
            }
        if(dir){
            int ilim=fpow(lim, mod-2);
            for(int i=0; i<lim; ++i) a[i]=mul(a[i], ilim);
        }
    }
    poly operator~(poly a){
        int n=a.size();
        poly b={fpow(a[0], mod-2)};
        a.resize(1<<(int)ceil(log2(n)));
        for(int lim=2; lim<2*n; lim<<=1){
            poly c(a.begin(), a.begin()+lim);
            c.resize(lim<<1), NTT(c, 0);
            b.resize(lim<<1), NTT(b, 0);
            for(int i=0; i<lim<<1; ++i) b[i]=mul(2+mod-mul(c[i], b[i]), b[i]);
            NTT(b, 1), b.resize(lim);
        }
        return b.resize(n), b;
    }
    poly log(poly a){
        int n=a.size();
        poly b=~a;
        for(int i=0; i<n-1; ++i) a[i]=mul(a[i+1], i+1);
        a.resize(n-1);
        int lim=1<<(int)ceil(log2(2*n-2));
        a.resize(lim), NTT(a, 0);
        b.resize(lim), NTT(b, 0);
        for(int i=0; i<lim; ++i) a[i]=mul(a[i], b[i]);
        NTT(a, 1), a.resize(n);
        for(int i=n-1; i>=1; --i) a[i]=mul(a[i-1], inv[i]);
        return a[0]=0, a;
    }
    poly exp(poly a){
        int n=a.size();
        poly b={1};
        a.resize(1<<(int)ceil(log2(n)));
        for(int lim=2; lim<2*n; lim<<=1){
            b.resize(lim); poly c=log(b);
            c[0]=add(1+a[0],mod-c[0]);
            for(int i=1; i<lim; ++i) c[i]=add(a[i],mod-c[i]);
            c.resize(lim<<1), NTT(c, 0);
            b.resize(lim<<1), NTT(b, 0);
            for(int i=0; i<lim<<1; ++i) b[i]=mul(c[i], b[i]);
            NTT(b, 1), b.resize(lim);
        }
        return b.resize(n), b;
    }
    poly operator*(poly a, poly b){
        int n=a.size()+b.size()-1, lim=1<<(int)ceil(log2(n));
        a.resize(lim), NTT(a, 0);
        b.resize(lim), NTT(b, 0);
        for(int i=0; i<lim; ++i) a[i]=mul(a[i], b[i]);
        NTT(a, 1), a.resize(n);
        return a;
    }
    
    int main(){
        init_NTT();
        int n=read<int>(), m=read<int>();
        poly a={1, 6, 1};
        a.resize(m+1), a=log(a);
        for(int i=0; i<=m; ++i) a[i]=mul(a[i], inv[2]);
        a=exp(a);
        poly b={1, 1};
        b.resize(m+1);
        for(int i=0; i<=m; ++i) b[i]=mul(b[i]+a[i], inv[2]);
        b=log(b);
        for(int i=0; i<=m; ++i) b[i]=mul(b[i], n+1);
        b=exp(b)*~a, b.resize(m+1);
        for(int i=1; i<=min(m, n); ++i) printf("%d%c", b[i], " \n"[i==m]);
        for(int i=min(m, n)+1; i<=m; ++i) printf("0%c", " \n"[i==m]);
        return 0;
    }
    
    静渊以有谋,疏通而知事。
  • 相关阅读:
    Entity Framework中的多个库操作批量提交、事务处理
    Entity Framework with NOLOCK
    在Entity Framework 中执行T-sql语句
    Entity Framework Extended Library (EF扩展类库,支持批量更新、删除、合并多个查询等)
    Visual Studio 2010 更新NuGet Package Manager出错解决办法
    html判断IE版本
    Java基础-学习笔记(七)——this关键字
    Java基础-学习笔记(六)——类的封装性
    Java基础-学习笔记(五)——面向过程和面向对象的区别
    Java基础-学习笔记(四)-流程控制
  • 原文地址:https://www.cnblogs.com/autoint/p/15630824.html
Copyright © 2011-2022 走看看