生活随笔
收集整理的這篇文章主要介紹了
[loj556][Antileaf's Round]咱们去烧菜吧
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
感覺挺套路的?
反正是付公主的背包的嚴格加強版
題目相關
鏈接
題目大意
給出nnn個商品,第iii個商品的體積為viv_ivi?,有bi個
現在給出一個mmm,對背包大小s∈[1,m]s\in[1,m]s∈[1,m]求填滿方案數
數據范圍
n≤100000,m≤100000n\le100000,m\le100000n≤100000,m≤100000
做法
此處引用[付公主的背包]一題的思路直接作修改了
考慮生成函數
對于第iii個物品我們構造生成函數fi(x)=∑j=0bixvijf_i(x)=\sum_{j=0}^{b_i}x^{v_ij}fi?(x)=j=0∑bi??xvi?j
進行等比數列求和
fi(x)=∑j=0bixvijf_i(x)=\sum_{j=0}^{b_i}x^{v_ij}fi?(x)=j=0∑bi??xvi?j
xvifi(x)=∑j=1bi+1xvijx^{v_i}f_i(x)=\sum_{j=1}^{b_i+1}x^{v_ij}xvi?fi?(x)=j=1∑bi?+1?xvi?j
相減得fi(x)?xvifi(x)=1?xvi(bi+1)f_i(x)-x^{v_i}f_i(x)=1-x^{v_i(b_i+1)}fi?(x)?xvi?fi?(x)=1?xvi?(bi?+1)
(1?xvi)fi(x)=1?xvi(bi+1)(1-x^{v_i})f_i(x)=1-x^{v_i(b_i+1)}(1?xvi?)fi?(x)=1?xvi?(bi?+1)
即fi(x)=1?xvi(bi+1)1?xvif_i(x)=\frac{1-x^{v_i(b_i+1)}}{1-x^{v_i}}fi?(x)=1?xvi?1?xvi?(bi?+1)?
所有生成函數相乘∏i=1nfi(x)\prod_{i=1}^nf_i(x)i=1∏n?fi?(x)
顯然答案的[1,m][1,m][1,m]次系數就是答案了
現在我們要快速求這個值,同樣的,我們進行lnlnln后進行加法再expexpexp回來的經典操作
根據lnlnln和expexpexp的定義,我們發現在lnlnln后除號都變成了減號,所以我們分別求分子分母的lnlnln值即可
根據付公主的背包中的推導已知道
ln(11?xv)=∑j=1∞1jxvjln(\frac1{1-x^v})=\sum_{j=1}^{\infty}\frac1jx^{vj}ln(1?xv1?)=j=1∑∞?j1?xvj
這樣的話ln(1?xv(b+1))ln(1-x^{v(b+1)})ln(1?xv(b+1))的值也就知道了,即
ln(11?xv(b+1))=∑j=1∞1jxv(b+1)jln(\frac1{1-x^{v(b+1)}})=\sum_{j=1}^{\infty}\frac1jx^{{v(b+1)}j}ln(1?xv(b+1)1?)=j=1∑∞?j1?xv(b+1)j
那么答案就是∑i=1n∑j=1∞(1jxvij?1jxvi(bi+1)j)\sum_{i=1}^n\sum_{j=1}^{\infty}\left(\frac1jx^{v_ij}-\frac1jx^{{v_i(b_i+1)}j}\right)i=1∑n?j=1∑∞?(j1?xvi?j?j1?xvi?(bi?+1)j)
我們將所有相同的系數合并,然后通過調和級數O(mlogm)\mathcal O(mlogm)O(mlogm)的時間復雜度獲得整個數組,最后再expexpexp,復雜度O(nlogn)\mathcal O(nlogn)O(nlogn)
其實兩題差不多
代碼
一樣的使用了多項式全套板子,所以會有點長
注意這題的輸入的n,m和付公主的背包含義不同
題目里碰到物品體積為0的情況要判掉(出題人沒判?),詳情見more這個變量相關的代碼
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<vector>
namespace fast_IO
{const int IN_LEN
=10000000,OUT_LEN
=10000000;char ibuf
[IN_LEN
],obuf
[OUT_LEN
],*ih
=ibuf
+IN_LEN
,*oh
=obuf
,*lastin
=ibuf
+IN_LEN
,*lastout
=obuf
+OUT_LEN
-1;inline char getchar_(){return (ih
==lastin
)&&(lastin
=(ih
=ibuf
)+fread(ibuf
,1,IN_LEN
,stdin),ih
==lastin
)?EOF:*ih
++;}inline void putchar_(const char x
){if(oh
==lastout
)fwrite(obuf
,1,oh
-obuf
,stdout),oh
=obuf
;*oh
++=x
;}inline void flush(){fwrite(obuf
,1,oh
-obuf
,stdout);}
}
using namespace fast_IO
;
#define getchar() getchar_()
#define putchar(x) putchar_((x))
typedef long long ll
;
#define rg register
template
<typename T
> inline T
max(const T a
,const T b
){return a
>b
?a
:b
;}
template
<typename T
> inline T
min(const T a
,const T b
){return a
<b
?a
:b
;}
template
<typename T
> inline T
mind(T
&a
,const T b
){a
=a
<b
?a
:b
;}
template
<typename T
> inline T
maxd(T
&a
,const T b
){a
=a
>b
?a
:b
;}
template
<typename T
> inline T
abs(const T a
){return a
>0?a
:-a
;}
template
<typename T
> inline void swap(T
&a
,T
&b
){T c
=a
;a
=b
;b
=c
;}
template
<typename T
> inline void swap(T
*a
,T
*b
){T c
=a
;a
=b
;b
=c
;}
template
<typename T
> inline T
gcd(const T a
,const T b
){if(!b
)return a
;return gcd(b
,a
%b
);}
template
<typename T
> inline T
square(const T x
){return x
*x
;};
template
<typename T
> inline void read(T
&x
)
{char cu
=getchar();x
=0;bool fla
=0;while(!isdigit(cu
)){if(cu
=='-')fla
=1;cu
=getchar();}while(isdigit(cu
))x
=x
*10+cu
-'0',cu
=getchar();if(fla
)x
=-x
;
}
template
<typename T
> void printe(const T x
)
{if(x
>=10)printe(x
/10);putchar(x
%10+'0');
}
template
<typename T
> inline void print(const T x
)
{if(x
<0)putchar('-'),printe(-x
);else printe(x
);
}
const int maxn
=2097152,mod
=998244353;
inline int Md(const int x
){return x
>=mod
?x
-mod
:x
;}
template
<typename T
>
inline int pow(int x
,T y
)
{rg
int res
=1;x
%=mod
;for(;y
;y
>>=1,x
=(ll
)x
*x
%mod
)if(y
&1)res
=(ll
)res
*x
%mod
;return res
;
}
namespace Poly
{
int W_
[maxn
],ha
[maxn
],hb
[maxn
],Inv
[maxn
];
inline void init(const int x
)
{rg
int tim
=0,lenth
=1;while(lenth
<x
)lenth
<<=1,tim
++;for(rg
int i
=1;i
<lenth
;i
<<=1){const int WW
=pow(3,(mod
-1)/(i
*2));W_
[i
]=1;for(rg
int j
=i
+1,k
=i
<<1;j
<k
;j
++)W_
[j
]=(ll
)W_
[j
-1]*WW
%mod
;}Inv
[0]=Inv
[1]=1;for(rg
int i
=2;i
<x
;i
++)Inv
[i
]=(ll
)(mod
-mod
/i
)*Inv
[mod
%i
]%mod
;
}
int L
;
inline void DFT(int*A
)
{for(rg
int i
=0,j
=0;i
<L
;i
++){if(i
>j
)swap(A
[i
],A
[j
]);for(rg
int k
=L
>>1;(j
^=k
)<k
;k
>>=1);}for(rg
int i
=1;i
<L
;i
<<=1)for(rg
int j
=0,J
=i
<<1;j
<L
;j
+=J
)for(rg
int k
=0;k
<i
;k
++){const int x
=A
[j
+k
],y
=(ll
)A
[j
+k
+i
]*W_
[i
+k
]%mod
;A
[j
+k
]=Md(x
+y
),A
[j
+k
+i
]=Md(mod
+x
-y
);}
}
void IDFT(int*A
)
{for(rg
int i
=1;i
<L
-i
;i
++)swap(A
[i
],A
[L
-i
]);DFT(A
);
}
inline int Quadratic_residue(const int a
)
{if(a
==0)return 0;int b
=(rand()<<14^rand())%mod
;while(pow(b
,(mod
-1)>>1)!=mod
-1)b
=(rand()<<14^rand())%mod
;int s
=mod
-1,t
=0,x
,inv
=pow(a
,mod
-2),f
=1;while(!(s
&1))s
>>=1,t
++,f
<<=1;t
--,x
=pow(a
,(s
+1)>>1),f
>>=1;while(t
){f
>>=1;if(pow((int)((ll
)inv
*x
%mod
*x
%mod
),f
)!=1)x
=(ll
)x
*pow(b
,s
)%mod
;t
--,s
<<=1;}return min(x
,mod
-x
);
}
struct poly
{std
::vector
<int>A
;poly(){A
.resize(0);}poly(const int x
){A
.resize(1),A
[0]=x
;}inline int&operator
[](const int x
){return A
[x
];}inline int operator
[](const int x
)const{return A
[x
];}inline void clear(){A
.clear();}inline unsigned int size()const{return A
.size();}inline void resize(const unsigned int x
){A
.resize(x
);}void RE(const int x
){A
.resize(x
);for(rg
int i
=0;i
<x
;i
++)A
[i
]=0; }void readin(const int MAX
){A
.resize(MAX
);for(rg
int i
=0;i
<MAX
;i
++)read(A
[i
]);}void putout()const{for(rg
unsigned int i
=0;i
<A
.size();i
++)print(A
[i
]),putchar(' ');}inline poly operator
+(const poly b
)const{poly RES
;RES
.resize(max(size(),b
.size()));for(rg
unsigned int i
=0;i
<RES
.size();i
++)RES
[i
]=Md((i
<size()?A
[i
]:0)+(i
<b
.size()?b
[i
]:0));return RES
;}inline poly operator
-(const poly b
)const{poly RES
;RES
.resize(max(size(),b
.size()));for(rg
unsigned int i
=0;i
<RES
.size();i
++)RES
[i
]=Md((i
<size()?A
[i
]:0)+mod
-(i
<b
.size()?b
[i
]:0));return RES
;}inline poly operator
*(const int b
)const{poly RES
=*this
;for(rg
unsigned int i
=0;i
<RES
.size();i
++)RES
[i
]=(ll
)RES
[i
]*b
%mod
;return RES
;}inline poly operator
/(const int b
)const{poly RES
=(*this
)*pow(b
,mod
-2);return RES
;}inline poly operator
*(const poly b
)const{const int RES
=A
.size()+b
.size()-1;L
=1;while(L
<RES
)L
<<=1;poly c
;c
.A
.resize(RES
);memset(ha
,0,L
<<2);memset(hb
,0,L
<<2);for(rg
unsigned int i
=0;i
<A
.size();i
++)ha
[i
]=A
[i
];for(rg
unsigned int i
=0;i
<b
.A
.size();i
++)hb
[i
]=b
.A
[i
];DFT(ha
),DFT(hb
);for(rg
int i
=0;i
<L
;i
++)ha
[i
]=(ll
)ha
[i
]*hb
[i
]%mod
;IDFT(ha
);const int inv
=pow(L
,mod
-2);for(rg
int i
=0;i
<RES
;i
++)c
.A
[i
]=(ll
)ha
[i
]*inv
%mod
;return c
;}inline poly
inv()const{poly C
;if(A
.size()==1){C
=*this
;C
[0]=pow(C
[0],mod
-2);return C
;}C
.resize((A
.size()+1)>>1);for(rg
unsigned int i
=0;i
<C
.size();i
++)C
[i
]=A
[i
];C
=C
.inv();L
=1;while(L
<(int)size()*2-1)L
<<=1;for(rg
unsigned int i
=0;i
<A
.size();i
++)ha
[i
]=A
[i
];for(rg
unsigned int i
=0;i
<C
.size();i
++)hb
[i
]=C
[i
];memset(ha
+A
.size(),0,(L
-A
.size())<<2);memset(hb
+C
.size(),0,(L
-C
.size())<<2);DFT(ha
),DFT(hb
);for(rg
int i
=0;i
<L
;i
++)ha
[i
]=(ll
)(2-(ll
)hb
[i
]*ha
[i
]%mod
+mod
)*hb
[i
]%mod
;IDFT(ha
);const int inv
=pow(L
,mod
-2);C
.resize(size());for(rg
unsigned int i
=0;i
<size();i
++)C
[i
]=(ll
)ha
[i
]*inv
%mod
;return C
;}
inline void Reverse(const int n
){A
.resize(n
);for(rg
int i
=0,j
=n
-1;i
<j
;i
++,j
--)swap(A
[i
],A
[j
]);}inline poly operator
/(const poly B
)const{if(size()<B
.size())return 0;poly a
=*this
,b
=B
;a
.Reverse(size()),b
.Reverse(B
.size());b
.resize(size()-B
.size()+1);b
=b
.inv();b
=b
*a
;b
.Reverse(size()-B
.size()+1);return b
;}inline poly operator
%(const poly B
)const{poly C
=(*this
)-(*this
)/B
*B
;C
.resize(B
.size()-1);return C
;}inline poly
diff()const{poly C
;C
.resize(size()-1);for(rg
unsigned int i
=1;i
<size();i
++)C
[i
-1]=(ll
)A
[i
]*i
%mod
;return C
;}inline poly
inte()const{poly C
;C
.resize(size()+1);for(rg
unsigned int i
=0;i
<size();i
++)C
[i
+1]=(ll
)A
[i
]*Inv
[i
+1]%mod
;C
[0]=0;return C
;}inline poly
ln()const{poly C
=(diff()*inv()).inte();C
.resize(size());return C
;}inline poly
exp()const{poly C
;if(size()==1){C
=*this
;C
[0]=1;return C
;}C
.resize((size()+1)>>1);for(rg
unsigned int i
=0;i
<C
.size();i
++)C
[i
]=A
[i
];C
=C
.exp();C
.resize(size());poly D
=(poly
)1-C
.ln()+*this
;D
=D
*C
;D
.resize(size());return D
;}inline poly
sqrt()const{poly C
;if(size()==1){C
=*this
;C
[0]=Quadratic_residue(C
[0]);return C
;}C
.resize((size()+1)>>1);for(rg
unsigned int i
=0;i
<C
.size();i
++)C
[i
]=A
[i
];C
=C
.sqrt();C
.resize(size());C
=(C
+*this
*C
.inv())*(int)499122177;C
.resize(size());return C
;}inline poly operator
>>(const unsigned int x
)const{poly C
;if(size()<x
){C
.resize(0);return C
;}C
.resize(size()-x
);for(rg
unsigned int i
=0;i
<C
.size();i
++)C
[i
]=A
[i
+x
];return C
;}inline poly operator
<<(const unsigned int x
)const{poly C
;C
.RE(size()+x
);for(rg
unsigned int i
=0;i
<size();i
++)C
[i
+x
]=A
[i
];return C
;}inline poly
Pow(const unsigned int x
)const{for(rg
unsigned int i
=0;i
<size();i
++)if(A
[i
]){poly C
=((((*this
/A
[i
])>>i
).ln()*x
).exp()*pow(A
[i
],x
))<<(min(i
*x
,size()));C
.resize(size());return C
;}return *this
;}inline void cheng(const poly
&B
){for(rg
unsigned int i
=0;i
<size();i
++)A
[i
]=(ll
)A
[i
]*B
[i
]%mod
; }inline void jia(const poly
&B
){for(rg
unsigned int i
=0;i
<size();i
++)A
[i
]=Md(A
[i
]+B
[i
]); }inline void dft(){memset(ha
,0,L
<<2);for(rg
unsigned int i
=0;i
<A
.size();i
++)ha
[i
]=A
[i
];DFT(ha
);resize(L
);for(rg
int i
=0;i
<L
;i
++)A
[i
]=ha
[i
];}inline void idft(){memset(ha
,0,L
<<2);for(rg
unsigned int i
=0;i
<A
.size();i
++)ha
[i
]=A
[i
];IDFT(ha
);const int inv
=pow(L
,mod
-2);for(rg
int i
=0;i
<L
;i
++)A
[i
]=(ll
)ha
[i
]*inv
%mod
;while(size()&&!A
[size()-1])A
.pop_back();}
};
void fz(const int root
,const int l
,const int r
,std
::vector
<int>&v
,std
::vector
<poly
>&A
)
{if(l
==r
){A
[root
].resize(2);A
[root
][0]=(mod
-v
[l
])%mod
;A
[root
][1]=1;return;}const int mid
=(l
+r
)>>1;fz(root
<<1,l
,mid
,v
,A
),fz(root
<<1|1,mid
+1,r
,v
,A
);A
[root
]=A
[root
<<1]*A
[root
<<1|1];
}
void calc(const int root
,const int l
,const int r
,std
::vector
<int>&v
,std
::vector
<poly
>&A
,std
::vector
<poly
>&B
)
{if(l
==r
){v
[l
]=B
[root
][0];return;}const int mid
=(l
+r
)>>1;B
[root
<<1]=B
[root
]%A
[root
<<1];B
[root
<<1|1]=B
[root
]%A
[root
<<1|1];calc(root
<<1,l
,mid
,v
,A
,B
),calc(root
<<1|1,mid
+1,r
,v
,A
,B
);
}
void multi_point_evaluation(const poly a
,std
::vector
<int>&v
)
{std
::vector
<poly
>A
,B
;A
.resize(maxn
),B
.resize(maxn
);fz(1,0,v
.size()-1,v
,A
);B
[1]=a
%A
[1];calc(1,0,v
.size()-1,v
,A
,B
);
}
void fz2(const int root
,const int l
,const int r
,std
::vector
<int>&y
,std
::vector
<poly
>&A
,std
::vector
<poly
>&B
)
{if(l
==r
){B
[root
].resize(1),B
[root
][0]=y
[l
];return;}const int mid
=(l
+r
)>>1;fz2(root
<<1,l
,mid
,y
,A
,B
),fz2(root
<<1|1,mid
+1,r
,y
,A
,B
);B
[root
]=B
[root
<<1]*A
[root
<<1|1]+B
[root
<<1|1]*A
[root
<<1];
}
poly
interpolation(std
::vector
<int>&x
,std
::vector
<int>&y
)
{std
::vector
<poly
>A
,B
;A
.resize(maxn
),B
.resize(maxn
);fz(1,0,x
.size()-1,x
,A
);multi_point_evaluation(A
[1].diff(),x
);for(rg
unsigned int i
=0;i
<x
.size();i
++)y
[i
]=(ll
)y
[i
]*pow(x
[i
],mod
-2)%mod
;fz2(1,0,x
.size()-1,y
,A
,B
);return B
[1];
}
}
int n
,m
;Poly
::poly a
;ll more
=1;
int main()
{Poly
::init(maxn
);read(m
),read(n
);a
.resize(m
+1);for(rg
int i
=1;i
<=n
;i
++){int v
,b
;read(v
),read(b
);if(v
==0){continue;}if(v
<=m
)a
[v
]=Md(a
[v
]+1);if(b
){const ll p
=(ll
)v
*(b
+1);if(p
<=m
)a
[p
]=Md(a
[p
]+998244352);}}for(rg
int i
=m
;i
>=1;i
--)for(rg
int j
=2;i
*j
<=m
;j
++)a
[i
*j
]=Md((ll
)a
[i
]*(Poly
::Inv
[j
])%mod
+a
[i
*j
]);a
=a
.exp();for(rg
int i
=1;i
<=m
;i
++)print(more
*a
[i
]%mod
),putchar('\n');return flush(),0;
}
總結
與付公主的背包差不多,還是很清真的
總結
以上是生活随笔為你收集整理的[loj556][Antileaf's Round]咱们去烧菜吧的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。