codeforces914GSum the Fibonacci FWT+FST(快速子集变换)

Posted GXZlegend

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces914GSum 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;
}

 

以上是关于codeforces914GSum the Fibonacci FWT+FST(快速子集变换)的主要内容,如果未能解决你的问题,请参考以下文章

CF 914 G Sum the Fibonacci —— 子集卷积,FWT

Codeforces 914C

Codeforces 914H

Codeforces 914 C Travelling Salesman and Special Numbers

codeforces 914E Palindromes in a Tree(点分治)

Codeforces - 914C 数位DP