洛谷题面传送门

首先 \(3^n\) 的做法就不多说了,相信对于会状压 dp+会枚举子集的同学来说不算困难(暴论),因此这篇博客将着重讲解 \(2^nn^2\) 的做法。

首先如果我们把每个 \(a_i\) 看作一个集合幂级数 \(1+x^{a_i}\),那么我们的任务就是把所有这样的集合幂级数做一遍子集卷积对吧。直接做一脸过不去。不过注意到这个式子的形式比较特别,事实上学过多项式&生成函数的同学应该对形如 \(1+x^k\) 的式子特别敏感,因为在生成函数那套理论中有个恒等式 \(\ln(1+x^k)=\sum\limits_{i}(-1)^{i+1}\dfrac{x^{ik}}{i}\),因此考虑将这东西与多项式扯上关系。考虑子集卷积的本质:将所有 \(x^{S}\) 看作一个二维函数 \(x^{S}y^{|S|}\),然后对 \(x\) 的指数做 or 卷积,对 \(y\) 的指数做加法卷积。那么我们考虑做这样一件事:把所有集合幂级数 \(F(S)\) 写成 \(\sum\limits_{S}F_{S}(y)x^S\) 的形式,也就是外层是集合幂级数,内层是一个关于 \(y\) 的多项式。那么考虑两个幂级数 \(F(S)\) 和 \(G(S)\) 做子集卷积得到的幂级数 \(H(S)\),必然有 \(H_i(y)=\sum\limits_{j|k=i}F_j(y)G_k(y)\),因此在这种定义下,对两个幂级数进行子集卷积的过程即是:将 \(F_{S}(y)x^S\) 做一遍 FWTor,也就是把平时对整数的 FWTor 的加法改为多项式加法,对 \(G_S(y)x^S\) 也做一遍同样的操作,然后令 \(H_S(y)=F_S(y)G_S(y)\),也就是将 FWT 后对应位置上的多项式卷起来,然后再 IFWTor 回去即可。

直接照着上面的方式做还是会 TLE,不过注意到将集合幂级数 \(1+x^{a_i}\) 进行一遍 FWTor 后得到的集合幂级数比较特别,具体来说,\(1=x^0y^0\) 显然可以对 FWTor 后所有位置上的数产生贡献,因此所有位置上的 \(F_S(y)\) 都有一个 \(y^0\),而 \(x^{a_i}=x^{a_i}y^{|a_i|}\) 显然只能对 \(a_i\in S\) 的 \(S\) 产生贡献,因此对于所有 \(a_i\in S\) 的 \(S\) 有 \(F_S(y)=y^{|a_i|}+1\),其余 \(S\) 有 \(F_{S}(y)=1\)。

它 出 现 了!\(y^{a_i}+1\) 显然与前面 \(1+x^k\) 是同一形式的,因此它的 \(\ln\) 我们也是可以非常轻松求得的,而我们在 FWTor 之后,按照套路是要把对应位置上的多项式全部卷起来的,按照多项式的套路我们可以先取 \(\ln\) 再 \(\exp\) 回去,看,你要的 \(\ln(y^{a_i}+1)\) 不就来了吗?我们记 \(H(S)\) 为将所有集合幂级数卷起来后得到的集合幂级数,那么对于所有 \(S\),\(\ln(\text{FWT}(H_S(y)))\) 是很好求的,具体步骤是:我们先记 \(F_{i,S}(y)\) 为一个幂级数,满足对于 \(S=a_i\),\(F_{i,S}(y)=\ln(y^{|a_i|}+1)\),其余 \(F_{i,S}=0\),对这东西对应位置上的多项式求个和,然后跑遍高维前缀和(或者你爱叫它 FWTor 我也没意见)即可,求完 \(\ln(H_S(y))\) 以后 \(\exp\) 回去即可得到 \(\text{FWT}(H_S(y))\),然后再一波 IFWTor 即可得到真正的系数,由于多项式的长度最多只有 \(18\),因此 \(\exp\) 不用任意模数 NTT,直接暴力求即可。

const int MAXN=1<<18;
const int LOG_V=18;
const int MOD=1e9+7;
int pr[MAXN/6+5],prcnt=0,vis[MAXN+5],phi[MAXN+5];
void sieve(int n){
phi[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]) pr[++prcnt]=i,phi[i]=i-1;
for(int j=1;j<=prcnt&&pr[j]*i<=n;j++){
vis[pr[j]*i]=1;
if(i%pr[j]==0){phi[i*pr[j]]=phi[i]*pr[j];break;}
phi[i*pr[j]]=phi[i]*phi[pr[j]];
}
}
}
int n,a[MAXN+5],f[MAXN+5][LOG_V+2],tmp[LOG_V+2],inv[LOG_V+2];
int main(){
scanf("%d",&n);sieve(MAXN);
for(int i=(inv[0]=inv[1]=1)+1;i<=LOG_V;i++) inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1,x;i<=n;i++) scanf("%d",&x),a[x]++;
for(int i=1;i<MAXN;i++){
int cnt=__builtin_popcount(i);
for(int j=1;j<=LOG_V/cnt;j++){
if(j&1) f[i][j*cnt]=(f[i][j*cnt]+1ll*inv[j]*a[i])%MOD;
else f[i][j*cnt]=(f[i][j*cnt]-1ll*inv[j]*a[i]%MOD+MOD)%MOD;
}
}
for(int i=2;i<=MAXN;i<<=1)
for(int j=0;j<MAXN;j+=i)
for(int k=0;k<(i>>1);k++)
for(int l=0;l<=LOG_V;l++){
f[(i>>1)+j+k][l]=(f[(i>>1)+j+k][l]+f[j+k][l])%MOD;
}
for(int i=0;i<MAXN;i++){
memset(tmp,0,sizeof(tmp));tmp[0]=1;
for(int j=1;j<=LOG_V;j++){
for(int k=0;k<j;k++)
tmp[j]=(tmp[j]+1ll*f[i][j-k]*(j-k)%MOD*tmp[k])%MOD;
tmp[j]=1ll*tmp[j]*inv[j]%MOD;
}
for(int j=0;j<=LOG_V;j++) f[i][j]=tmp[j];
}
for(int i=2;i<=MAXN;i<<=1)
for(int j=0;j<MAXN;j+=i)
for(int k=0;k<(i>>1);k++)
for(int l=0;l<=LOG_V;l++){
f[(i>>1)+j+k][l]=(f[(i>>1)+j+k][l]-f[j+k][l]+MOD)%MOD;
}
int ans=0;
for(int i=0;i<MAXN;i++) ans=(ans+1ll*phi[i+1]*f[i][__builtin_popcount(i)])%MOD;
for(int i=1;i<=a[0];i++) ans=2*ans%MOD;
printf("%d\n",ans);
return 0;
}

洛谷 P6570 - [NOI Online #3 提高组] 优秀子序列(集合幂级数+多项式)的更多相关文章

  1. luogu P6570 [NOI Online #3 提高组]优秀子序列 二进制 dp

    LINK:P6570 [NOI Online #3 提高组]优秀子序列 Online 2的T3 容易很多 不过出于某种原因(时间不太够 浪了 导致我连暴力的正解都没写. 容易想到 f[i][j]表示前 ...

  2. 洛谷 P6478 - [NOI Online #2 提高组] 游戏(二项式反演+树形 dp)

    题面传送门 没错这就是我 boom0 的那场 NOIOL 的 T3 一年前,我在 NOIOL #2 的赛场上折戟沉沙,一年后,我从倒下的地方爬起. 我成功了,我不再是从前那个我了 我们首先假设 A 拥 ...

  3. 洛谷P1003 铺地毯 noip2011提高组day1T1

    洛谷P1003 铺地毯 noip2011提高组day1T1 洛谷原题 题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n ...

  4. 洛谷-神奇的幻方-NOIP2015提高组复赛

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,--,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

  5. 洛谷 P1541 乌龟棋 & [NOIP2010提高组](dp)

    传送门 解题思路 一道裸的dp. 用dp[i][j][k][kk]表示用i个1步,j个2步,k个3步,kk个4步所获得的最大价值,然后状态转移方程就要分情况讨论了(详见代码) 然后就是一开始统计一下几 ...

  6. 洛谷 P1525 关押罪犯 & [NOIP2010提高组](贪心,种类并查集)

    传送门 解题思路 很显然,为了让最大值最小,肯定就是从大到小枚举,让他们分在两个监狱中,第一个不符合的就是答案. 怎样判断是否在一个监狱中呢? 很显然,就是用种类并查集. 种类并查集的讲解——团伙(很 ...

  7. 洛谷 P5019 铺设道路 & [NOIP2018提高组](贪心)

    题目链接 https://www.luogu.org/problem/P5019 解题思路 一道典型的贪心题. 假设从左往右填坑,如果第i个深与第i+1个,那么第i+1个就不需要额外填: 如果第i+1 ...

  8. 洛谷P1063 能量项链 [2006NOIP提高组]

    P1063 能量项链 题目描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标 记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子 ...

  9. 「洛谷P1080」「NOIP2012提高组」国王游戏 解题报告

    P1080 国王游戏 题目描述 恰逢 \(H\)国国庆,国王邀请\(n\)位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 \( ...

随机推荐

  1. FastAPI 学习之路(四十六)WebSockets(二)

    上一篇文章,我们分享了WebSockets一些入门的,我们这节课,在原来的基础上,对于讲解的进行一个演示.我们最后分享了依赖token等.首先我们对上次的代码进行调整. 我们之前分享FastAPI 学 ...

  2. Elasticsearch 中为什么选择倒排索引而不选择 B 树索引

    目录 前言 为什么全文索引不使用 B+ 树进行存储 全文检索 正排索引 倒排索引 倒排索引如何存储数据 FOR 压缩 RBM 压缩 倒排索引如何存储 字典树(Tria Tree) FST FSM 构建 ...

  3. CentOS 文件管理

    目录 目录管理 目录结构 切换目录 查看目录 创建目录 复制目录 剪切目录 删除目录 文件管理 查看文件 创建文件 复制文件 剪切文件 删除文件 创建链接 目录管理 目录也是一种文件. 蓝色目录,绿色 ...

  4. Alpha-技术规格说明书

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 团队项目-计划-功能规格说明书 一.架构与技术栈 1.整体架构 本项目的整体架构如上图所示.下面我们将对涉及 ...

  5. skywalking实现分布式系统链路追踪

    一.背景 随着微服务的越来越流行,我们服务之间的调用关系就显得越来越复杂,我们急需一个APM工具来分析系统中存在的各种性能指标问题以及调用关系.目前主流的APM工具有CAT.Zipkin.Pinpoi ...

  6. Python之@property详解及底层实现介绍

    转自:https://blog.csdn.net/weixin_42681866/article/details/83376484 前文 Python内置有三大装饰器:@staticmethod(静态 ...

  7. hdu 2999 Stone Game, Why are you always there? (简单SG,有个优化)

    题意: 一排石头,个数是K. 有n个数,a1...an. 每人每次取石子只能取连续的x个.x属于a1...an的一个. 没法取者负. 思路: 简单的SG.但是TLE!后面加了一个优化~这个优化不好想到 ...

  8. Iptables 代理局域网内的主机上网

    参考连接:https://developer.aliyun.com/article/607330 环境为云环境,有外网主机的IP为192.168.0.39,无外网主机的IP为192.168.0.228 ...

  9. Socket `accept queue is full ` 但是一个连接需要从SYN->ACCEPT

    由于标题长度有限制,我把想要描述的问题再次描述下: 内核通常会为每一个LISTEN状态的Socket维护两个队列: 1 accept队列: listen()函数第二个参数BACKLOG指定,表示已完成 ...

  10. 谷粒 | 项目集成redis

    添加依赖 由于redis缓存是公共应用,所以我们把依赖与配置添加到了common模块下面,在common模块pom.xml下添加以下依赖 <!-- redis --> <depend ...