zoukankan      html  css  js  c++  java
  • #4155. 咱们去烧菜吧

    题意
    内存限制:512 MiB
    时间限制:1000 ms

    你有 $m$ 种物品,第 $i$ 种物品的大小为 $a_i$,数量为 $b_i$($b_i=0$ 表示有无限个)。

    你还有 $n$ 个背包,体积分别为 $1$ 到 $n$,现在你很想知道用这些物品填满某个背包的方案数。

    为了满足你的好奇心,你决定把填满每个背包的方案数都算一遍。

    因为你其实只是闲得无聊,所以你只想知道方案数对 $998244353$($7 imes 17 imes 2^{23}+1$,一个质数)取模后的值。

    $0< n,mle 10^5, 0le a_ile 110000,0le b_ile 10^6$。

    题解

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

    那么当 $b_i=0$ 时, $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}^n(ln (1-x^{a_i imes (b_i+1)})-ln(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",&n,&m);
        for (int x,y,i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            if (x<=n) a[x]++;
            if (y && 1ll*x*(y+1)<=1ll*n)
                a[x*(y+1)]--;
        }
        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;
            if (a[i]<0) a[i]+=P;
            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;
    }
  • 相关阅读:
    常见寻找OEP脱壳的方法
    Windows内核原理系列01
    HDU 1025 Constructing Roads In JGShining's Kingdom
    HDU 1024 Max Sum Plus Plus
    HDU 1003 Max Sum
    HDU 1019 Least Common Multiple
    HDU 1018 Big Number
    HDU 1014 Uniform Generator
    HDU 1012 u Calculate e
    HDU 1005 Number Sequence
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/10679284.html
Copyright © 2011-2022 走看看