Description

给出 \(n\) 个 \(\leq m\) 且不同的数 \(a_1,\dots,a_n\),现在要求从这 \(n\) 个数中选出最少的数字,满足这 \(n\) 个数字都可以由选出的数字组合成(就是做一个完全背包能做出来),并且任意组合出来的数字,只要不超过 \(m\),就必须让这个数字在给出的 \(n\) 个数中。问是否可行,如果可行,请求出最少选多少数字。 \(n,m\leq 10^6\)。

Sol

先判断是否可行,再看哪些数可以省略。

求出 \(a\) 数组的生成函数,即构造多项式 \(F(x)=\sum f_i\cdot x^i\)。\(f_i\) 为 \(1\) 当且仅当 \(a\) 数组中出现 \(a_*=i\)

然后求出 \(G(x)=F^2(i)=\sum g_i\cdot x^i\)。如果 \(g_i>0\) 那就说明给出的这 \(n\) 个数可以合成 \(i\) 。

于是就得到了从原来的 \(n\) 个数中拿出 \(0\sim 2\) 个的结果。

然而最多拿出 \(m\) 个。

所以还要继续,用快速幂求得 \(f^m\)。如果多项式快速幂的话,复杂度 \(O(n\log^2n)\),用多项式ln+多项式exp求的话,复杂度 \(O(n\log n)\)。但是多项式exp常数太大了!

事实上是有只做 \(1\) 次FFT的方法的。

显然如果 \(f_i>0\) 的话,\(g_i>0\)。

那我们只要保证满足 \(f_i=0,g_i>0,i\leq m\) 的 \(i\) 不存在就好了。

如果第一轮不存在这些不合法的,那接下来肯定也不存在。感性理解一下这就相当于构成了一个封闭的集合。

所以只做 \(1\) 次FFT就行了。

然后考虑一下哪些数可以省略

如果一个数 \(i\) 可以被其他数表示出来,那 \(g_i\) 一定 \(>2\)。所以 \(g_i=2\) 的 \(i\) 就是必选的。

时间复杂度 \(O(n\log n)\)。

Sol

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using std::min;
using std::max;
using std::swap;
using std::vector;
typedef double db;
typedef long long ll;
#define pb(A) push_back(A)
#define pii std::pair<int,int>
#define all(A) A.begin(),A.end()
#define mp(A,B) std::make_pair(A,B)
const int N=4e6+5;
const int mod=998244353; int lim,rev[N];
int n,m,a[N],b[N]; int ksm(int a,int b=mod-2,int ans=1){
while(b){
if(b&1) ans=1ll*ans*a%mod;
a=1ll*a*a%mod;b>>=1;
} return ans;
} int getint(){
int X=0,w=0;char ch=getchar();
while(!isdigit(ch))w|=ch=='-',ch=getchar();
while( isdigit(ch))X=X*10+ch-48,ch=getchar();
if(w) return -X;return X;
} void ntt(int *f,int g){
for(int i=1;i<lim;i++) if(i<rev[i]) swap(f[i],f[rev[i]]);
for(int mid=1;mid<lim;mid<<=1){
int tmp=ksm(g,(mod-1)/(mid<<1));
for(int R=mid<<1,j=0;j<lim;j+=R){
int w=1;
for(int k=0;k<mid;k++,w=1ll*w*tmp%mod){
int x=f[j+k],y=1ll*w*f[j+k+mid]%mod;
f[j+k]=(x+y)%mod,f[j+k+mid]=(mod+x-y)%mod;
}
}
} if(g>3)
for(int in=ksm(lim),i=0;i<lim;i++) f[i]=1ll*f[i]*in%mod;
} signed main(){
n=getint(),m=getint();
for(int i=1;i<=n;i++){
int x=getint();
a[x]=b[x]=1;
}
lim=1;while(lim<=m+m) lim<<=1;
for(int i=1;i<lim;i++) rev[i]=(rev[i>>1]>>1)|(i&1?lim>>1:0);
a[0]=1; ntt(a,3);
for(int i=0;i<lim;i++) a[i]=1ll*a[i]*a[i]%mod;
ntt(a,(mod+1)/3);
for(int i=1;i<=m;i++)
if(a[i] and !b[i]) return printf("NO"),0;
puts("YES"); int tot=0;
for(int i=1;i<=m;i++)
if(a[i]==2) tot++;
printf("%d\n",tot);
for(int i=1;i<=m;i++)
if(a[i]==2) printf("%d ",i);
return 0;
}

[CF286E] Ladies' shop的更多相关文章

  1. CF286E Ladies' Shop FFT

    题目链接 读完题后,我们发现如下性质: 在合法且和不超过 $m$ 的情况下,如果 $a_{i}$ 出现,则 $a_{i}$ 的倍数也必出现. 所以如果合法,只要对所有数两两结合一次就能得到所有 $a_ ...

  2. codeforces 286 E. Ladies' Shop (FFT)

    E. Ladies' Shop time limit per test 8 seconds memory limit per test 256 megabytes input standard inp ...

  3. codeforces 286E Ladies' Shop

    题目大意:n个小于等于m的数,现在你需要在[1,m]中选择若干个数,使得选出的数能组成的所有数正好与n个数相同,给出最少要选多少个数. 题目分析: 结论一:选择的若干个数一定在n个数中. 证明:否则的 ...

  4. CodeForces 286E Ladies' Shop 多项式 FFT

    原文链接http://www.cnblogs.com/zhouzhendong/p/8781889.html 题目传送门 - CodeForces 286E 题意 首先,给你$n$个数(并告诉你$m$ ...

  5. Ladies' Shop

    题意: 有 $n$ 个包,设计最少的物品体积(可重集),使得 1. 对于任意一个总体积不超过给定 $m$ 的物体集合有其体积和 恰好等于一个包的容量. 2.对于每一个包,存在一个物品集合能恰好装满它. ...

  6. Codeforces 286E - Ladies' Shop(FFT)

    Codeforces 题面传送门 & 洛谷题面传送门 好久没刷过 FFT/NTT 的题了,写篇题解罢( 首先考虑什么样的集合 \(T\) 符合条件.我们考察一个 \(x\in S\),根据题意 ...

  7. 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】

    原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...

  8. Codeforces Round #176 (Div. 1 + Div. 2)

    A. IQ Test 模拟. B. Pipeline 贪心. C. Lucky Permutation 每4个数构成一个循环. 当n为偶数时,n=4k有解:当n为奇数时,n=4k+1有解. D. Sh ...

  9. codeforces 632+ E. Thief in a Shop

    E. Thief in a Shop time limit per test 5 seconds memory limit per test 512 megabytes input standard ...

随机推荐

  1. 线程中的setDaemon方法

    setDaemon方法必须在start方法前定义.t1.setDaemon(True),该语句的意思是:将主线程A设置为子线程t1的守护线程.也就是在执行程序时,t1会随着主线程A的退出而退出,不论t ...

  2. Unity3D中AssetBundle应用

    工程中的模型等资源转化为Prefab后,打包成AssetBundle,可以大幅降低资源的空间占有度,并且提高资源加载的效率. 一.AssetBundle的打包 先看下打包Prefab的脚本代码,这段脚 ...

  3. Paper | 学习多任务中的最佳分/ 合结构(十字绣结构)

    目录 1. 问题 2. 十字绣结构(Cross-stitch architecture) 3. 实验设计 论文:Cross-stitch Networks for Multi-task Learnin ...

  4. kubernetes1.7.6 ha高可用部署

    写在前面:  1. 该文章部署方式为二进制部署. 2. 版本信息 k8s 1.7.6,etcd 3.2.9 3. 高可用部分 etcd做高可用集群.kube-apiserver 为无状态服务使用hap ...

  5. JDBC数据库

    JDBC是Java程序连接和存取数据库的应用程序接口(API),包括两个包:java.sql和javax.sql. 用JDBC访问数据库的一般步骤: 1.建立数据源 2.装入JDBC驱动程序:使用Cl ...

  6. linux vg lv pv

    = pv由物理卷或者分区组成   pv可以组成一个或者多个vg     vg可以分成多个lv 方便扩展 pvs vgs lvs 可以查看当前存在的pv vg lv 我的centos硬盘20g 使用了一 ...

  7. 05 详解C# 迭代器

    迭代器模式是设计模式中行为模式(behavioral pattern)的一个例子,他是一种简化对象间通讯的模式,也是一种非常容易理解和使用的模式. 简单来说,迭代器模式使得你能够获取到序列中的所有元素 ...

  8. 包建强的培训课程(12):iOS深入学习(内存管理、Block和GCD等)

    @import url(/css/cuteeditor.css); @import url(http://i.cnblogs.com/Load.ashx?type=style&file=Syn ...

  9. 深度学习Tensorflow生产环境部署(下·模型部署篇)

    前一篇讲过环境的部署篇,这一次就讲讲从代码角度如何导出pb模型,如何进行服务调用. 1 hello world篇 部署完docker后,如果是cpu环境,可以直接拉取tensorflow/servin ...

  10. 全栈开发工程师微信小程序-中(中)

    全栈开发工程师微信小程序-中(中) 开放能力 open-data 用于展示微信开放的数据 type 开放数据类型 open-gid 当 type="groupName" 时生效, ...