• 【刷题】LOJ 556 「Antileaf's Round」咱们去烧菜吧


    题目描述

    烧菜

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

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

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

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

    输入格式

    第一行两个非负整数,分别表示 (n,m)

    以下 (m) 行,每行两个非负整数,分别表示 (a_i,b_i) ​。

    输出格式

    输出 (n) 个非负整数表示答案。

    样例

    样例输入

    5 3
    1 0
    1 1
    3 2
    

    样例输出

    2
    2
    3
    4
    4
    

    样例解释

    拼出 (1) ~ (5) 的方案分别如下:

    ({1_1},{1_2})

    ({1_1,1_1},{1_1,1_2})

    ({1_1,1_1,1_1},{1_1,1_1,1_2},{3})

    ({1_1,1_1,1_1,1_1},{1_1,1_1,1_1,1_2},{1_1,3},{1_2,3})

    ({1_1,1_1,1_1,1_1,1_1},{1_1,1_1,1_1,1_1,1_2},{1_1,1_1,3},{1_1,1_2,3})

    数据范围与提示

    (0<n,m leq 10^5,0 leq a_i​ leq 110000,0 leq b_i leq 10^6)

    题解

    数量无限的物品的生成函数为:(sum_{i=0}^{+infty}x^{ia_i}=frac{1}{1-x^{a_i}})

    数量有限的物品的生成函数为:(sum_{i=0}^{b_i}x^{ia_i}=frac{1-x^{(b_i+1)a_i}}{1-x^{a_i}})

    将所有物品的生成函数乘起来就是答案的生成函数,即(假设全部都有限):

    (egin{aligned} ans &= prod_{i=1}^mfrac{1-x^{(b_i+1)a_i}}{1-x^{a_i}} \ &= exp{sum_{i=1}^m (ln (1-x^{(b_i+1)a_i})-ln (1-x^{a_i}))} end{aligned})

    然后我们知道:(-ln(1-x)=sum_{i=1}^{+infty}frac{x^i}{i}) ,所以

    (ln (1-x^{(b_i+1)a_i})=sum_{i=1}^{+infty}-frac{1}{i}x^{(b_i+1)a_i})

    (ln (1-x^{a_i})=sum_{i=1}^{+infty}-frac{1}{i}x^{a_i})

    那么对于物品,可以 (O(n ln{n} )) 地把它们的贡献加到OGF上,然后做多项式exp就好了

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    #define ft first
    #define sd second
    #define pb(a) push_back(a)
    #define PII std::pair<int,int>
    #define PLL std::pair<ll,ll>
    #define mp(a,b) std::make_pair(a,b)
    #define ITR(a,b) for(auto a:b)
    #define REP(a,b,c) for(register int a=(b),a##end=(c);a<=a##end;++a)
    #define DEP(a,b,c) for(register int a=(b),a##end=(c);a>=a##end;--a)
    const int MAXN=1<<21,Mod=998244353;
    int M[MAXN];
    ll OGF[MAXN],ans[MAXN];
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline bool chkmin(T &x,T y){return y<x?(x=y,true):false;}
    template<typename T> inline bool chkmax(T &x,T y){return y>x?(x=y,true):false;}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    namespace poly{
    	const int Mod=998244353;
    	int rev[MAXN];
    	ll b[MAXN],c[MAXN],tmp[MAXN],inv2,inv3,invm,pw[MAXN],ipw[MAXN],iv[MAXN];
    	inline ll qexp(ll a,ll b)
    	{
    		ll res=1;
    		while(b)
    		{
    			if(b&1)res=res*a%Mod;
    			a=a*a%Mod;
    			b>>=1;
    		}
    		return res;
    	}
    	inline void init(int n)
    	{
    		inv2=qexp(2,Mod-2);inv3=qexp(3,Mod-2);
    		for(register int l=1;l<=(n<<2);l<<=1)
    			pw[l]=qexp(3,(Mod-1)/l),ipw[l]=qexp(inv3,(Mod-1)/l);
    		REP(i,1,n+n+1)iv[i]=qexp(i,Mod-2);
    	}
    	inline void NTT(ll *A,int n,int tp)
    	{
    		REP(i,0,n-1)if(i<rev[i])std::swap(A[i],A[rev[i]]);
    		for(register int l=2;l<=n;l<<=1)
    		{
    			ll wn=tp>0?pw[l]:ipw[l];
    			for(register int i=0;i<n;i+=l)
    			{
    				ll w=1;
    				for(register int j=0;j<(l>>1);++j)
    				{
    					ll A1=A[i+j],A2=1ll*A[i+j+(l>>1)]*w%Mod;
    					A[i+j]=(A1+A2)%Mod,A[i+j+(l>>1)]=(A1-A2+Mod)%Mod;
    					w=1ll*w*wn%Mod;
    				}
    			}
    		}
    	}
    	inline void Get_Mul(int n,ll *A,ll *B,ll *C)
    	{
    		int m,cnt;
    		for(m=1,cnt=0;m<n;m<<=1,++cnt);
    		REP(i,0,m-1)rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
    		NTT(A,m,1);NTT(B,m,1);
    		REP(i,0,m-1)A[i]=1ll*A[i]*B[i]%Mod;
    		NTT(A,m,-1);
    		invm=qexp(m,Mod-2);
    		REP(i,0,n-1)C[i]=1ll*A[i]*invm%Mod;
    	}
    	inline void Get_Inv(int len,ll *A,ll *B)
    	{
    		if(len==1)
    		{
    			B[0]=qexp(A[0],Mod-2);
    			return ;
    		}
    		Get_Inv((len+1)>>1,A,B);
    		int m,cnt;
    		for(m=1,cnt=0;m<(len<<1);m<<=1,++cnt);
    		REP(i,0,m-1)rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
    		REP(i,0,len-1)tmp[i]=A[i];
    		REP(i,len,m-1)tmp[i]=0;
    		NTT(tmp,m,1);NTT(B,m,1);
    		REP(i,0,m-1)B[i]=(2ll*B[i]%Mod-1ll*B[i]*B[i]%Mod*tmp[i]%Mod+Mod)%Mod;
    		NTT(B,m,-1);
    		invm=qexp(m,Mod-2);
    		REP(i,0,len-1)B[i]=1ll*B[i]*invm%Mod;
    		REP(i,len,m-1)B[i]=0;
    	}
    	inline void Get_Sqr(int len,ll *A,ll *B)
    	{
    		if(len==1)
    		{
    			B[0]=1;
    			return ;
    		}
    		Get_Sqr((len+1)>>1,A,B);
    		memset(b,0,sizeof(b));Get_Inv(len,B,b);
    		int m,cnt;
    		for(m=1,cnt=0;m<(len<<1);m<<=1,++cnt);
    		REP(i,0,m-1)rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
    		REP(i,0,len-1)tmp[i]=A[i];
    		REP(i,len,m-1)tmp[i]=0;
    		NTT(B,m,1);NTT(tmp,m,1);NTT(b,m,1);
    		REP(i,0,m-1)B[i]=1ll*(tmp[i]+1ll*B[i]*B[i]%Mod)%Mod*b[i]%Mod*inv2%Mod;
    		NTT(B,m,-1);
    		invm=qexp(m,Mod-2);
    		REP(i,0,len-1)B[i]=1ll*B[i]*invm%Mod;
    		REP(i,len,m-1)B[i]=0;
    	}
    	inline void Get_Div(int n1,ll *A,int n2,ll *B,ll *C,ll *D)
    	{
    		memset(c,0,sizeof(c));
    		REP(i,0,n2-1)c[i]=B[n2-1-i];
    		Get_Inv(n1-n2+1,c,b);
    		int m,cnt;
    		for(m=1,cnt=0;m<((n1-n2+1)<<1);m<<=1,++cnt);
    		REP(i,0,m-1)rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
    		REP(i,0,n1-n2)tmp[i]=A[n1-1-i];
    		REP(i,n1-n2+1,m-1)tmp[i]=0;
    		NTT(tmp,m,1);NTT(b,m,1);
    		REP(i,0,m-1)tmp[i]=1ll*tmp[i]*b[i]%Mod;
    		NTT(tmp,m,-1);
    		invm=qexp(m,Mod-2);
    		memset(c,0,sizeof(c));
    		REP(i,0,n1-n2)C[n1-n2-i]=c[n1-n2-i]=1ll*tmp[i]*invm%Mod;
    		for(m=1,cnt=0;m<n1;m<<=1,++cnt);
    		REP(i,0,m-1)rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
    		NTT(B,m,1);NTT(c,m,1);
    		REP(i,0,m-1)B[i]=1ll*B[i]*c[i]%Mod;
    		NTT(B,m,-1);
    		invm=qexp(m,Mod-2);
    		REP(i,0,n2-2)D[i]=(A[i]-1ll*B[i]*invm%Mod+Mod)%Mod;
    	}
    	inline void Get_Der(int n,ll *A,ll *B)
    	{
    		REP(i,0,n-2)B[i]=1ll*A[i+1]*(i+1)%Mod;B[n-1]=0;
    	}
    	inline void Get_Int(int n,ll *A,ll *B)
    	{
    		REP(i,1,n-1)B[i]=1ll*A[i-1]*iv[i]%Mod;B[0]=0;
    	}
    	inline void Get_Ln(int n,ll *A,ll *B)
    	{
    		memset(b,0,sizeof(b));
    		Get_Inv(n,A,b);Get_Der(n,A,c);
    		int m,cnt;
    		for(m=1,cnt=0;m<(n<<1);m<<=1,++cnt);
    		REP(i,0,m-1)rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
    		NTT(b,m,1);NTT(c,m,1);
    		REP(i,0,m-1)b[i]=1ll*b[i]*c[i]%Mod;
    		NTT(b,m,-1);
    		invm=qexp(m,Mod-2);
    		REP(i,0,n-1)b[i]=1ll*b[i]*invm%Mod;
    		Get_Int(n,b,B);
    	}
    	inline void Get_Exp(int len,ll *A,ll *B)
    	{
    		if(len==1)
    		{
    			B[0]=1;
    			return ;
    		}
    		Get_Exp((len+1)>>1,A,B);Get_Ln(len,B,c);
    		int m,cnt;
    		for(m=1,cnt=0;m<(len<<1);m<<=1,++cnt);
    		REP(i,0,m-1)rev[i]=(rev[i>>1]>>1)|((i&1)<<(cnt-1));
    		REP(i,0,len-1)tmp[i]=(A[i]-c[i]+(i==0)+Mod)%Mod;
    		REP(i,len,m-1)tmp[i]=0;
    		NTT(tmp,m,1);NTT(B,m,1);
    		REP(i,0,m-1)B[i]=1ll*tmp[i]*B[i]%Mod;
    		NTT(B,m,-1);
    		invm=qexp(m,Mod-2);
    		REP(i,0,len-1)B[i]=1ll*B[i]*invm%Mod;
    		REP(i,len,m-1)B[i]=0;
    	}
    }
    int main()
    {
    	int n,m;read(n);read(m);poly::init(n+1);
    	REP(i,1,m)
    	{
    		int a,b;read(a);read(b);
    		if(a<=n)M[a]++;
    		if(1ll*(b+1)*a<=n&&b)M[(b+1)*a]--;
    	}
    	REP(i,1,n)if(M[i])REP(j,1,n/i)OGF[i*j]=((OGF[i*j]+1ll*M[i]*poly::iv[j]%Mod)%Mod+Mod)%Mod;
    	poly::Get_Exp(n+1,OGF,ans);
    	REP(i,1,n)write(ans[i],'
    ');
    	return 0;
    }
    
  • 相关阅读:
    1166
    SpringBoot(八) Caching
    将本地项目上传到码云
    《码出高效 Java开发手册》
    Sourcetree报错: 您没有已经配置扩展集成设置的远端
    看准网免登陆查看
    redis入门基础
    Java泛型类型
    SpringBoot(七) Working with data: SQL
    ORA-12514: TNS:监听程序当前无法识别连接描述符中请求的服务
  • 原文地址:https://www.cnblogs.com/hongyj/p/10518744.html
Copyright © 2020-2023  润新知