zoukankan      html  css  js  c++  java
  • CF286E Ladies' Shop

    Ladies' Shop

    首先,给你(n)个数(并告诉你(m)),分别为(p_{1dots n})

    让你求一个数的集合,满足:

    当且仅当从这个数的集合中取数(可以重复)求和时(设得到的和为(sum)),如果(sumleq m),则数(sum)在给你的(n)个数之中。且(n)个数都要被组合出来。

    如果没有这种集合,输出NO。

    否则,先输出YES,然后输出这个集合最小时的元素个数,并输出集合中的所有元素。

    (1leq n,mleq 10^6,1leq p_ileq 10^6)

    题解

    因为(a)中元素全部要出现,他们的组合也会出现,所以写出数集的01生成函数(a),并令(a_0=1)

    那么(a^2)的意义是至多选两个组合得到的。若存在(ile m,a_i=0,a^2_i>0),则说明组合出的元素不合题意,即无解。若不存在这样的情况,那么(a)的任意正整数次方都是一样的。

    那么有解的情况下如何判断最少选多少呢?考虑若(i)不能被其他元素组合,则(a^2_i=2),即(i)(0)组合的方案数。若(a^2_i>2),则说明(i)能被其他元素组合出来。那么去掉这些多余的即可。

    使用FFT优化多项式乘法,时间复杂度(O(n log n))

    struct node {double x,y;};
    il node operator+(co node&a,co node&b){
        return (node){a.x+b.x,a.y+b.y};
    }
    il node operator-(co node&a,co node&b){
        return (node){a.x-b.x,a.y-b.y};
    }
    il node operator*(co node&a,co node&b){
        return (node){a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x};
    }
    il node operator/(co node&a,double k){
        return (node){a.x/k,a.y/k};
    }
    
    co double pi=acos(-1);
    co int N=1<<21;
    int n,m,a[N],b[N];
    int len,lim,rev[N];
    node c[N];
    
    void fourier_trans(node a[],int inv){
    	for(int i=0;i<lim;++i)if(i<rev[i]) swap(a[i],a[rev[i]]);
    	for(int step=1;step<lim;step<<=1){
    		double alpha=inv*pi/step;
    		for(int k=0;k<step;++k){
    			node omega=(node){cos(alpha*k),sin(alpha*k)};
    			for(int even=k;even<lim;even+=step<<1){
    				int odd=even+step;node t=omega*a[odd];
    				a[odd]=a[even]-t,a[even]=a[even]+t;
    			}
    		}
    	}
    	if(inv==-1)for(int i=0;i<lim;++i) a[i]=a[i]/lim;
    }
    
    int main(){
    	read(n),read(m);
    	a[0]=1;
    	for(int i=1;i<=n;++i) a[read<int>()]=1;
    	len=ceil(log2(2*m+1)),lim=1<<len;
    	for(int i=0;i<lim;++i){
    		rev[i]=rev[i>>1]>>1|(i&1)<<(len-1);
    		c[i]=(node){i<=m?a[i]:0,0};
    	}
    	fourier_trans(c,1);
    	for(int i=0;i<lim;++i) c[i]=c[i]*c[i];
    	fourier_trans(c,-1);
    	for(int i=1;i<=m;++i) b[i]=round(c[i].x);
    	bool valid=1;int cnt=0;
    	for(int i=1;i<=m;++i){
    		if(!a[i]&&b[i]) {valid=0;break;}
    		else if(b[i]==2) ++cnt;
    	}
    	if(!valid) puts("NO");
    	else{
    		printf("YES
    %d
    ",cnt);
    		for(int i=1;i<=m;++i)if(b[i]==2) printf("%d ",i);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Composite in Javascript
    Model Validation in Asp.net MVC
    HttpRuntime.Cache vs. HttpContext.Current.Cache
    Controller Extensibility in ASP.NET MVC
    The Decorator Pattern in Javascript
    The Flyweight Pattern in Javascript
    Model Binding in ASP.NET MVC
    Asp.net MVC
    jQuery Ajax 实例 全解析
    ASP.NET AJAX入门系列
  • 原文地址:https://www.cnblogs.com/autoint/p/11265969.html
Copyright © 2011-2022 走看看