1 条题解
-
0
题解
物品的生成函数为,对所有物品生成函数做分治乘法卷积,多项式项系数即为恰好装满的方案数。
#include<bits/stdc++.h> #define int long long using namespace std; using PII=std::pair<int,int>; using i64=long long; template<class T> constexpr T power(T a,i64 b) { T res=1; for(;b;b/=2,a*=a){ if(b%2)res*=a; } return res; } constexpr i64 mul(i64 a,i64 b,i64 p){ i64 res=a*b-i64(1.L*a*b/p)*p; res%=p; if(res<0)res+=p; return res; } template<int P> struct MInt{ int x; constexpr MInt():x{}{} constexpr MInt(i64 x):x{norm(x % getMod())}{} static int Mod; constexpr static int getMod(){ if(P>0)return P; else return Mod; } constexpr static void setMod(int Mod_){ Mod=Mod_; } constexpr int norm(int x)const{ if(x<0)x+=getMod(); if(x>=getMod())x-=getMod(); return x; } constexpr int val()const{ return x; } explicit constexpr operator int() const{ return x; } constexpr MInt operator-() const{ MInt res; res.x=norm(getMod()-x); return res; } constexpr MInt inv() const{ assert(x!=0); return power(*this,getMod()-2); } constexpr MInt &operator*=(MInt rhs)&{ x=1LL*x*rhs.x%getMod(); return *this; } constexpr MInt &operator+=(MInt rhs)&{ x=norm(x+rhs.x); return *this; } constexpr MInt &operator-=(MInt rhs)&{ x=norm(x-rhs.x); return *this; } constexpr MInt &operator/=(MInt rhs)&{ return *this*=rhs.inv(); } friend constexpr MInt operator*(MInt lhs,MInt rhs){ MInt res=lhs; res*=rhs; return res; } friend constexpr MInt operator+(MInt lhs,MInt rhs){ MInt res=lhs; res+=rhs; return res; } friend constexpr MInt operator-(MInt lhs,MInt rhs){ MInt res=lhs; res-=rhs; return res; } friend constexpr MInt operator/(MInt lhs,MInt rhs){ MInt res=lhs; res/=rhs; return res; } friend constexpr std::istream &operator>>(std::istream &is,MInt &a){ i64 v; is>>v; a=MInt(v); return is; } friend constexpr std::ostream &operator<<(std::ostream &os,const MInt &a){ return os<<a.val(); } friend constexpr bool operator==(MInt lhs, MInt rhs){ return lhs.val()==rhs.val(); } friend constexpr bool operator!=(MInt lhs, MInt rhs){ return lhs.val()!=rhs.val(); } }; template<> int MInt<0>::Mod=998244353; template<int V, int P> constexpr MInt<P> CInv = MInt<P>(V).inv(); constexpr i64 P=998244353; using Z=MInt<P>; std::vector<int> rev; template<i64 P> std::vector<Z> roots{0,1}; template<i64 P> constexpr MInt<P> findPrimitiveRoot(){ MInt<P> i=2; int k=__builtin_ctz(P-1); while(true){ if(power(i,(P-1)/2)!=1)break; i+=1; } return power(i,(P-1)>>k); } template<i64 P> constexpr MInt<P> primitiveRoot = findPrimitiveRoot<P>(); template<> constexpr MInt<998244353> primitiveRoot<998244353> {31}; template<i64 P> constexpr void dft(std::vector<MInt<P>> &a) { int n=a.size(); if(rev.size()!=n){ int k=__builtin_ctz(n)-1; rev.resize(n); for(int i=0;i<n;i++){ rev[i]=rev[i>>1]>>1|(i&1)<<k; } } for(int i=0;i<n;i++){ if(rev[i]<i){ std::swap(a[i],a[rev[i]]); } } if(roots<P>.size()<n){ int k=__builtin_ctz(roots<P>.size()); roots<P>.resize(n); while((1ll<<k)<n){ auto e=power(primitiveRoot<P>,1ll<<(__builtin_ctz(P-1)-k-1)); for(int i=1ll<<(k-1);i<1ll<<k;i++){ roots<P>[i<<1]=roots<P>[i]; roots<P>[i<<1|1]=roots<P>[i]*e; } k++; } } for(int k=1;k<n;k*=2){ for(int i=0;i<n;i+=k*2){ for(int j=0;j<k;j++){ auto u=a[i+j]; auto v=a[i+j+k]*roots<P>[k+j]; a[i+j]=u+v; a[i+j+k]=u-v; } } } } template<i64 P> constexpr void idft(std::vector<MInt<P>> &a){ int n=a.size(); std::reverse(a.begin()+1,a.end()); dft(a); Z inv=(1-P)/n; for(int i=0;i<n;i++)a[i]*=inv; } template<i64 P=998244353> struct Poly:public std::vector<MInt<P>>{ using Value=MInt<P>; Poly():std::vector<Value>(){} explicit constexpr Poly(int n):std::vector<Value>(n){} explicit constexpr Poly(const std::vector<Value>&a):std::vector<Value>(a){} constexpr Poly(const std::initializer_list<Value> &a):std::vector<Value>(a){} template<class InputIt,class=std::_RequireInputIter<InputIt>> explicit constexpr Poly(InputIt first,InputIt last):std::vector<Value>(first,last){} template<class F> explicit constexpr Poly(int n,F f):std::vector<Value>(n){ for(int i=0;i<n;i++){ (*this)[i]=f(i); } } constexpr Poly shift(int k)const{ if(k>=0){ auto b=*this; b.insert(b.begin(),k,0); return b; }else if(this->size()<=-k){ return Poly(); }else{ return Poly(this->begin()+(-k),this->end()); } } constexpr Poly trunc(int k)const{ Poly f=*this; f.resize(k); return f; } constexpr friend Poly operator+(const Poly &a,const Poly &b){ Poly res(std::max(a.size(),b.size())); for(int i=0;i<a.size();i++){ res[i]+=a[i]; } for(int i=0;i<b.size();i++){ res[i]+=b[i]; } return res; } constexpr friend Poly operator-(const Poly &a,const Poly &b){ Poly res(std::max(a.size(),b.size())); for(int i=0;i<a.size();i++){ res[i]+=a[i]; } for(int i=0;i<b.size();i++){ res[i]-=b[i]; } return res; } constexpr friend Poly operator-(const Poly &a){ std::vector<Value>res(a.size()); for(int i=0;i<res.size();i++){ res[i]=-a[i]; } return Poly(res); } constexpr friend Poly operator*(Poly a,Poly b){ if(a.size()==0||b.size()==0){ return Poly(); } if(a.size()<b.size()){ std::swap(a,b); } int n=1,tot=a.size()+b.size()-1; while(n<tot){n*=2;} if(((P-1)&(n-1))!=0||b.size()<128){ Poly c(a.size()+b.size()-1); for(int i=0;i<a.size();i++){ for(int j=0;j<b.size();j++){ c[i+j]+=a[i]*b[j]; } } return c; } a.resize(n); b.resize(n); dft(a); dft(b); for(int i=0;i<n;i++){ a[i]*=b[i]; } idft(a); a.resize(tot); return a; } constexpr friend Poly operator*(Value a,Poly b){ for(int i=0;i<b.size();i++){ b[i]*=a; } return b; } constexpr friend Poly operator*(Poly a,Value b){ for(int i=0;i<a.size();i++){ a[i]*=b; } return a; } constexpr friend Poly operator/(Poly a,Value b){ for(int i=0;i<a.size();i++){ a[i]/=b; } return a; } constexpr Poly &operator+=(Poly b){ return (*this)=(*this)+b; } constexpr Poly &operator-=(Poly b){ return (*this)=(*this)-b; } constexpr Poly &operator*=(Poly b){ return (*this)=(*this)*b; } constexpr Poly &operator*=(Value b){ return (*this)=(*this)*b; } constexpr Poly &operator/=(Value b){ return (*this)=(*this)/b; } }; void solve(){ i64 n,m;std::cin>>n>>m; std::vector<i64> v(n),c(n); for(int i=0;i<n;i++)std::cin>>v[i]; for(int i=0;i<n;i++)std::cin>>c[i]; std::vector<Poly<P>> P(n,Poly(1e5+1)); for(int i=0;i<n;i++){ for(int j=0;v[i]*c[i]*j<=1e5;j++){ P[i][v[i]*c[i]*j]=1; } } Poly ans=P[0]; for(int i=1;i<n;i++)ans*=P[i]; while(m--){ int V;std::cin>>V; std::cout<<ans[V]<<'\n'; } } signed main(){ std::cin.tie(nullptr); std::ios::sync_with_stdio(false); std::cout<<std::fixed<<std::setprecision(10); int T=1; //std::cin>>T; while(T--)solve(); return 0; }
- 1
信息
- ID
- 279
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- (无)
- 递交数
- 32
- 已通过
- 11
- 上传者