[CF286E] Ladies' shop
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的更多相关文章
- CF286E Ladies' Shop FFT
		题目链接 读完题后,我们发现如下性质: 在合法且和不超过 $m$ 的情况下,如果 $a_{i}$ 出现,则 $a_{i}$ 的倍数也必出现. 所以如果合法,只要对所有数两两结合一次就能得到所有 $a_ ... 
- codeforces 286 E. Ladies' Shop (FFT)
		E. Ladies' Shop time limit per test 8 seconds memory limit per test 256 megabytes input standard inp ... 
- codeforces 286E Ladies' Shop
		题目大意:n个小于等于m的数,现在你需要在[1,m]中选择若干个数,使得选出的数能组成的所有数正好与n个数相同,给出最少要选多少个数. 题目分析: 结论一:选择的若干个数一定在n个数中. 证明:否则的 ... 
- CodeForces 286E Ladies' Shop 多项式 FFT
		原文链接http://www.cnblogs.com/zhouzhendong/p/8781889.html 题目传送门 - CodeForces 286E 题意 首先,给你$n$个数(并告诉你$m$ ... 
- Ladies' Shop
		题意: 有 $n$ 个包,设计最少的物品体积(可重集),使得 1. 对于任意一个总体积不超过给定 $m$ 的物体集合有其体积和 恰好等于一个包的容量. 2.对于每一个包,存在一个物品集合能恰好装满它. ... 
- Codeforces 286E - Ladies' Shop(FFT)
		Codeforces 题面传送门 & 洛谷题面传送门 好久没刷过 FFT/NTT 的题了,写篇题解罢( 首先考虑什么样的集合 \(T\) 符合条件.我们考察一个 \(x\in S\),根据题意 ... 
- 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】
		原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ... 
- 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 ... 
- 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 ... 
随机推荐
- idea使用自动生成变量的时候总是默认final,每次都会跳出来declare final的选项,并且默认是勾选的,很难受
			看下截图: 我这边首先要保证:settings----->Editor------>Code Style-------->java下的这两个选项不被勾选; 然后在生成变量的时候,再次 ... 
- 2.0vue导出excel
			如果没有插件导入 import FileSaver from 'file-saver' import XLSX from 'xlsx'导入依赖 import FileSaver from 'file- ... 
- python学习总结(一)
			1.编码格式发展历史 ASCII 255 Ibytes --> 1980 gb2312 7000+ -->1995 GBK1.0 2W+ -->2000 GB18030 2.7W+ ... 
- 下载安装配置Maven
			下载安装Apache Maven 1.Maven官网下载jia包:http://maven.apache.org/download.cgi 2.将文件解压到D:\Program Files\apach ... 
- ssh框架 基本整合
			struts的基本配置 <struts> <constant name="struts.devModel" value="true" /> ... 
- 【react】利用shouldComponentUpdate钩子函数优化react性能以及引入immutable库的必要性
			凡是参阅过react官方英文文档的童鞋大体上都能知道对于一个组件来说,其state的改变(调用this.setState()方法)以及从父组件接受的props发生变化时,会导致组件重渲染,正所谓&qu ... 
- python jieba库的基本使用
			第一步:先安装jieba库 输入命令:pip install jieba jieba库常用函数: jieba库分词的三种模式: 1.精准模式:把文本精准地分开,不存在冗余 2.全模式:把文中所有可能的 ... 
- Material Design 开源项目总结
			Android开发中,我们不免会遇到Material Design展示的需求,以下是本人之前star的开源项目,供大家参考: 一.RippleEffect 项目地址:https://github.co ... 
- #Java学习之路——基础阶段(第一篇)
			我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ... 
- Spark基础-scala学习(二、面向对象)
			面向对象编程之类 //定义一个简单的类 scala> :paste // Entering paste mode (ctrl-D to finish) //类默认public的 class He ... 
