zoukankan      html  css  js  c++  java
  • 洛谷P4389 付公主的背包

    题目描述

    题解

    烧菜的弱化版

    把第 $i$ 个物品的生成函数写出, $F_i(x)=sum_{j=0}^{infty} x^{a_i imes j}=frac{1}{1-x^{a_i}}$

    则最后的答案的生成函数 $G(x)=prod_{i=1}^nF_i(x)$

    两边取对数,即 $ln G(x)=ln (prod_{i=1}^nF_i(x))=sum_{i=1}^n ln F_i(x)=-sum_{i=1}^nln(1-x^{a_i})$

    又知道 $ln(1-x^k)=-sum_{i=1}^{infty} frac{x^{i imes k}}{i}$

    所以对于每个 $k$ ,都会对 $x^{i imes k}$ 的系数造成影响,所以这一部分可以 $O(nln n)$ 预处理

    所以最后做个多项式 $exp$ 即可

    代码

    #include <bits/stdc++.h>
    #define I inline
    using namespace std;
    const int P=998244353,N=5e5+5;
    int n,m,a[N],b[N],r[N],t,p,G[2]={3,332748118};
    int A[N],B[N],C[N],D[N],E[N],F[N],jc[N],ny[N];
    I int X(int x){if (x>=P) x-=P;return x;}
    I int inv(int x){return 1ll*jc[x-1]*ny[x]%P;}
    I int K(int x,int y){
        int A=1;
        for (;y;y>>=1,x=1ll*x*x%P)
            if (y&1) A=1ll*A*x%P;
        return A;
    }
    I void Ntt(int *g,bool o){
        for (int i=0;i<t;i++)
            if (i<r[i]) swap(g[i],g[r[i]]);
        for (int wn,i=1;i<t;i<<=1){
            wn=K(G[o],(P-1)/(i<<1));
            for (int x,y,j=0;j<t;j+=(i<<1))
                for (int w=1,k=0;k<i;k++,w=1ll*w*wn%P)
                    x=g[j+k],y=1ll*w*g[i+j+k]%P,
                    g[j+k]=X(x+y),g[i+j+k]=X(x-y+P);
        }
        if (o)
            for (int i=0,v=K(t,P-2);i<t;i++)
                g[i]=1ll*v*g[i]%P;
    }
    I void dao(int *a,int *b,int l){
        for (int i=1;i<l;i++)
            b[i-1]=1ll*i*a[i]%P;
        b[l]=b[l-1]=0;
    }
    I void jifen(int *a,int *b,int l){
        for (int i=1;i<l;i++)
            b[i]=1ll*a[i-1]*inv(i)%P;
        b[0]=0;
    }
    I void pre(int l){
        for (t=1,p=0;t<l+l;t<<=1,p++);
        for (int i=0;i<t;i++)
            r[i]=(r[i>>1]>>1)|((i&1)<<(p-1));
    }
    I void getinv(int *a,int *b,int l){
        if (l==1){
            b[0]=K(a[0],P-2);return;
        }
        getinv(a,b,(l+1)>>1);
        for (int i=0;i<l;i++)
            A[i]=a[i],B[i]=b[i];
        pre(l);Ntt(A,0);Ntt(B,0);
        for (int i=0;i<t;i++)
            A[i]=1ll*A[i]*B[i]%P*B[i]%P;
        Ntt(A,1);for (int i=0;i<l;i++)
            b[i]=X(X(b[i]+b[i])-A[i]+P);
        for (int i=0;i<t;i++) A[i]=B[i]=0;
    }
    I void getln(int *a,int *b,int l){
        dao(a,C,l);getinv(a,D,l);
        pre(l);Ntt(C,0);Ntt(D,0);
        for (int i=0;i<t;i++)
            C[i]=1ll*C[i]*D[i]%P;
        Ntt(C,1);jifen(C,b,l);
        for (int i=0;i<t;i++) C[i]=D[i]=0;
    }
    I void getexp(int *a,int *b,int l){
        if (l==1){b[0]=1;return;}
        getexp(a,b,(l+1)>>1);
        for (int i=0;i<l;i++) E[i]=b[i];
        getln(b,F,l);
        for (int i=0;i<l;i++)
            F[i]=X(a[i]-F[i]+P);
        F[0]=X(F[0]+1);pre(l);
        Ntt(F,0);Ntt(E,0);
        for (int i=0;i<t;i++)
            E[i]=1ll*E[i]*F[i]%P;
        Ntt(E,1);
        for (int i=0;i<l;i++) b[i]=E[i];
        for (int i=0;i<t;i++) E[i]=F[i]=0;
    }
    int main(){
        scanf("%d%d",&m,&n);
        for (int x,i=1;i<=m;i++){
            scanf("%d",&x);
            if (x<=n) a[x]++;
        }
        jc[0]=1;
        for (int i=1;i<=n;i++)
            jc[i]=1ll*i*jc[i-1]%P;
        ny[n]=K(jc[n],P-2);
        for (int i=n;i;i--)
            ny[i-1]=1ll*i*ny[i]%P;
        for (int i=1;i<=n;i++){
            if (!a[i]) continue;
            for (int j=1;j*i<=n;j++)
                b[i*j]=X(b[i*j]+1ll*a[i]*inv(j)%P);
            a[i]=0;
        }
        getexp(b,a,n+1);
        for (int i=1;i<=n;i++)
            printf("%d
    ",a[i]);
        return 0;
    }
  • 相关阅读:
    JSP内置对象——application,page,pageContext,config,Exception
    点击按钮添加一组下拉框,然后改变下拉框的值触发事件
    vue基础学习(三)
    轻量级quill富文本编辑器
    jQuery 文档操作方法
    点击识别位置并在该位置下弹出选择框
    css样式清零及常用类
    vue基础学习(二)
    响应式web-媒体查询
    在cmd下编译一个简单的servlet时出现程序包javax.servlet不存在
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/12266257.html
Copyright © 2011-2022 走看看