【codeforces914G】Sum the Fibonacci FWT+FST(快速子集变换)
给出一个长度为 $n$ 的序列 $\{s\}$ ,对于所有满足以下条件的五元组 $(a,b,c,d,e)$ :
- $1\le a,b,c,d,e\le n$ ;
- $(s_a|s_b)\&s_c\&(s_d\text{^}s_e)=2^i$ ,其中 $i$ 为非负整数 ;
- $s_a\&s_b=0$ 。
求 $f(s_a|s_b)\times f(s_c)\times f(s_d\text{^}s_e)$ 的和模 $10^9+7$,其中 $f(i)$ 表示斐波那契数列的第 $i$ 项( $f(0)=0,f(1)=1$ )。
题解
FWT+FST(Fast-Subset-Transform)
显然是求 $cnt[s_a]$ 和 $cnt[s_b]$ 的子集卷积得出 $cnt[s_a|s_b]$ ,求 $cnt[s_d]$ 和 $cnt[s_e]$ 的异或卷积得出 $cnt[s_d\text{^}s_e]$ ,然后求 $cnt[s_a|s_b]\times f[s_a|s_b]$ 、$cnt[s_c]\times f[s_c]$ 、$cnt[s_d\text{^}s_e]\times f[s_d\text{^}s_e]$ 的与卷积,与卷积的 $2^i$ 项之和即为答案。
(子集卷积:$c$ 是 $a$ 和 $b$ 的子集卷积,当且仅当:$c[i]=\sum\limits_{j|k=i,j\&k=0}a[j]\times b[k]$ ,直观理解上等价于 $c[i]=\sum\limits_{j\in i}a[j]\times b[i-j]$ ,故称子集卷积)
异或卷积和与卷积可以直接使用FWT计算。
子集卷积的计算方法可以参考vfk集训队论文中提到的占位多项式法:
$j|k=i,j\&k=0$ 等价于 $j|k=i,|j|+|k|=|i|$ 。
因此求 $c'[p][i]=\sum\limits_{j|k=i,|j|+|k|=p}a[j]\times b[k]=\sum\limits_{j|k=i,|j|+|k|=p}a'[|j|][j]\times b'[|k|][k]=\sum\limits_{j|k=i,q+r=p}a'[q][j]+b'[r][k]$ ,那么 $c[i]=c'[|i|][i]$ 。
其中 $|i|$ 表示 $i$ 集合的大小,即 $i$ 二进制中 $1$ 的个数。$a'[|i|][i]=a[i]$ ,其余为0;$b'$ 同理。
那么我们对每一个 $a'[q][]$ 和 $b'[r][]$ 分别求DWT,然后进行类似背包合并的卷积,再求IDWT即可。这个部分的时间复杂度为 $O(2^{17}·17^2)$ 。
因此总的时间复杂度为 $O(2^{17}·17^2+2^{17}·17·常数)$ 。
这里我脑残了... $cnt[s_a,s_b,s_c,s_d,s_e]$ 都是一样的,因此可以减少DWT的次数... 不管了反正A了...
#include <cstdio>
#include <algorithm>
#define N 131100
#define mod 1000000007
#define inv 500000004
using namespace std;
typedef long long ll;
int s[1000010] , cnt[N];
ll fib[N] , a[18][N] , b[18][N] , c[N] , d[N] , e[N] , f[18][N];
int main()
{
int n , m = 1 , mx = 0 , k , i , j;
ll t , ans = 0;
scanf("%d" , &n);
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &s[i]) , mx = max(mx , s[i]);
while(m <= mx) m <<= 1;
fib[1] = 1;
for(i = 2 ; i < m ; i ++ ) fib[i] = (fib[i - 1] + fib[i - 2]) % mod;
for(i = 1 ; i < m ; i ++ ) cnt[i] = cnt[i - (i & -i)] + 1;
for(i = 1 ; i <= n ; i ++ ) a[cnt[s[i]]][s[i]] ++ , b[cnt[s[i]]][s[i]] ++ , c[s[i]] ++ , d[s[i]] ++ , e[s[i]] ++ ;
for(i = 0 ; i < m ; i ++ ) c[i] = c[i] * fib[i] % mod;
for(i = 1 ; i < m ; i <<= 1) for(j = 0 ; j < m ; j ++ ) if(i & j) t = d[j] , d[j] = (d[j - i] - t + mod) % mod , d[j - i] = (d[j - i] + t) % mod;
for(i = 1 ; i < m ; i <<= 1) for(j = 0 ; j < m ; j ++ ) if(i & j) t = e[j] , e[j] = (e[j - i] - t + mod) % mod , e[j - i] = (e[j - i] + t) % mod;
for(i = 0 ; i < m ; i ++ ) d[i] = d[i] * e[i] % mod;
for(i = 1 ; i < m ; i <<= 1) for(j = 0 ; j < m ; j ++ ) if(i & j) t = d[j] , d[j] = (d[j - i] - t + mod) * inv % mod , d[j - i] = (d[j - i] + t) * inv % mod;
for(i = 0 ; i < m ; i ++ ) d[i] = d[i] * fib[i] % mod;
for(k = 0 ; k <= cnt[m - 1] ; k ++ )
{
for(i = 1 ; i < m ; i <<= 1) for(j = 0 ; j < m ; j ++ ) if(i & j) a[k][j] = (a[k][j] + a[k][j - i]) % mod;
for(i = 1 ; i < m ; i <<= 1) for(j = 0 ; j < m ; j ++ ) if(i & j) b[k][j] = (b[k][j] + b[k][j - i]) % mod;
}
for(i = 0 ; i <= cnt[m - 1] ; i ++ )
for(j = 0 ; j <= cnt[m - 1] - i ; j ++ )
for(k = 0 ; k < m ; k ++ )
f[i + j][k] = (f[i + j][k] + a[i][k] * b[j][k]) % mod;
for(k = 0 ; k <= cnt[m - 1] ; k ++ ) for(i = 1 ; i < m ; i <<= 1) for(j = 0 ; j < m ; j ++ ) if(i & j) f[k][j] = (f[k][j] - f[k][j - i] + mod) % mod;
for(i = 0 ; i < m ; i ++ ) e[i] = f[cnt[i]][i] * fib[i] % mod;
for(i = 1 ; i < m ; i <<= 1) for(j = 0 ; j < m ; j ++ ) if(i & j) c[j - i] = (c[j - i] + c[j]) % mod;
for(i = 1 ; i < m ; i <<= 1) for(j = 0 ; j < m ; j ++ ) if(i & j) d[j - i] = (d[j - i] + d[j]) % mod;
for(i = 1 ; i < m ; i <<= 1) for(j = 0 ; j < m ; j ++ ) if(i & j) e[j - i] = (e[j - i] + e[j]) % mod;
for(i = 0 ; i < m ; i ++ ) c[i] = c[i] * d[i] % mod * e[i] % mod;
for(i = 1 ; i < m ; i <<= 1) for(j = 0 ; j < m ; j ++ ) if(i & j) c[j - i] = (c[j - i] - c[j] + mod) % mod;
for(i = 1 ; i < m ; i <<= 1) ans = (ans + c[i]) % mod;
printf("%lld\n" , ans);
return 0;
}
【codeforces914G】Sum the Fibonacci FWT+FST(快速子集变换)的更多相关文章
- 知识点简单总结——FWT(快速沃尔什变换),FST(快速子集变换)
知识点简单总结--FWT(快速沃尔什变换),FST(快速子集变换) 闲话 博客园的markdown也太傻逼了吧. 快速沃尔什变换 位运算卷积 形如 $ f[ i ] = \sum\limits_{ j ...
- codeforces914G Sum the Fibonacci
题目大意:给定一个长为$n$($n\leq 10^6$)的序列S,定义一个合法的五元组$(a,b,c,d,e)$合法当且仅当 $$ ( S_a \mid S_b ) and S_c and ( S_d ...
- 快速沃尔什变换(FWT) 与 快速莫比乌斯变换 与 快速沃尔什变换公式推导
后面的图片将会告诉: 如何推出FWT的公式tf 如何推出FWT的逆公式utf 用的是设系数,求系数的方法! ============================================== ...
- 快速沃尔什变换(FWT)及K进制异或卷积&快速子集变换(FST)讲解
前言: $FWT$是用来处理位运算(异或.与.或)卷积的一种变换.位运算卷积是什么?形如$f[i]=\sum\limits_{j\oplus k==i}^{ }g[j]*h[k]$的卷积形式(其中$\ ...
- CF914G Sum the Fibonacci FWT、子集卷积
传送门 一道良心的练习FWT和子集卷积的板子-- 具体来说就是先把所有满足\(s_a \& s_b = 0\)的\(s_a \mid s_b\)的值用子集卷积算出来,将所有\(s_a \opl ...
- Codeforces914G Sum the Fibonacci(FWT)
FWT大杂烩.跟着模拟做很多次FWT即可. #include<iostream> #include<cstdio> #include<cmath> #include ...
- FWT,FST入门
0.目录 目录 0.目录 1.什么是 FWT 2. FWT 怎么做 2.1. 或卷积 2.2.与卷积 2.3.异或卷积 2.4.例题 3. FST 3.1. FST 怎么做 3.2.例题 1.什么是 ...
- CF914G Sum the Fibonacci(FWT,FST)
CF914G Sum the Fibonacci(FWT,FST) Luogu 题解时间 一堆FWT和FST缝合而来的丑陋产物. 对 $ cnt[s_{a}] $ 和 $ cnt[s_{b}] $ 求 ...
- 【CF914G】Sum the Fibonacci 快速??变换模板
[CF914G]Sum the Fibonacci 题解:给你一个长度为n的数组s.定义五元组(a,b,c,d,e)是合法的当且仅当: 1. $1\le a,b,c,d,e\le n$2. $(s_a ...
随机推荐
- 《Java 程序设计》课堂实践三
实践题目 编写MyOD.java 用java MyOD XXX实现Linux下od -tx -tc XXX的功能 提交测试代码和运行结果截图,加上学号水印,提交码云代码链接. 代码链接 代码链接 实践 ...
- 真香!iOS云真机全新上线!
WeTest 导读 众多开发者已经渐渐适应通过调用线上的安卓真机进行远程调试,但是针对iOS设备,则依然存在“iOS设备昂贵”“无法及时采购iOS最新设备”“无法复现iOS历史系统版本”等问题. 为了 ...
- iframe ie低版本 横向滚动条的解决办法
吐槽下百度,在百度搜这个问题都是渣渣,谷歌直接就出来了,记录一下 设置Frame时,有一属性是scrolling="yes/no/auto",IE6的mozilla都支持,或许对a ...
- moment.js使用方法总结
Moment.js是一个轻量级的JavaScript时间库,它方便了日常开发中对时间的操作,提高了开发效率.日常开发中,通常会对时间进行下面这几个操作:比如获取时间,设置时间,格式化时间,比较时间等等 ...
- MySQL高性能优化实战总结
1.1 前言 MySQL对于很多Linux从业者而言,是一个非常棘手的问题,多数情况都是因为对数据库出现问题的情况和处理思路不清晰.在进行MySQL的优化之前必须要了解的就是MySQL的查询过程,很多 ...
- Python爬虫下载Bilibili番剧弹幕
本文绍如何利用python爬虫下载bilibili番剧弹幕. 准备: python3环境 需要安装BeautifulSoup,selenium包 phantomjs 原理: 通过aid下载bilibi ...
- CsvHelper文档-4映射
CsvHelper文档-4映射 类映射 有时候你的类成员和csv的header不一定对应,有时候你的csv文件根本就没有header行,你需要特别制定一个成员的index,你不能依靠.net中默认的顺 ...
- 二维DCT变换
DCT(Discrete Consine Transform),又叫离散余弦变换,它的第二种类型,经常用于信号和图像数据的压缩.经过DCT变换后的数据能量非常集中,一般只有左上角的数值是非零的,也就是 ...
- 如何使用phpredis连接Redis的方法
本文跟大家介绍使用同一VPC内弹性云服务器ECS上的phpredis连接Redis的方法. 更多的客户端的使用方法,请参考https://redis.io/clients 前提条件 已成功申请Redi ...
- java读取excel或者csv时日期格式数据处理
背景:最近写一个通过excel批量导入数据的功能,里面含有时间,但是java读取之后把时间转为了距离1990年1月1号的天数,比如excel中时间为2018/9/16 18:30,java读取之后变成 ...