CF286E Ladies' Shop

Ladies' Shop

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

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

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

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

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

\(1\leq n,m\leq 10^6,1\leq p_i\leq 10^6\)

题解

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

那么\(a^2\)的意义是至多选两个组合得到的。若存在\(i\le 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\n%d\n",cnt);
		for(int i=1;i<=m;++i)if(b[i]==2) printf("%d ",i);
	}
	return 0;
}

posted on 2019-07-29 19:31  autoint  阅读(121)  评论(0编辑  收藏  举报

导航