1 条题解

  • 0
    @ 2024-12-12 8:12:56

    题解

    物品ii的生成函数为xc[i]v[i]k\sum x^{c[i]*v[i]*k},对所有物品生成函数做分治乘法卷积,多项式xVx^V项系数即为恰好装满VV的方案数。

    #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
    上传者