zoukankan      html  css  js  c++  java
  • 【codeforces914G】Sum the Fibonacci FWT+FST(快速子集变换)

    题目描述

    给出一个长度为 $n$ 的序列 ${s}$ ,对于所有满足以下条件的五元组 $(a,b,c,d,e)$ :

    • $1le a,b,c,d,ele n$ ;
    • $(s_a|s_b)&s_c&(s_d ext{^}s_e)=2^i$ ,其中 $i$ 为非负整数 ;
    • $s_a&s_b=0$ 。

    求 $f(s_a|s_b) imes f(s_c) imes f(s_d ext{^}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 ext{^}s_e]$ ,然后求 $cnt[s_a|s_b] imes f[s_a|s_b]$ 、$cnt[s_c] imes f[s_c]$ 、$cnt[s_d ext{^}s_e] imes f[s_d ext{^}s_e]$ 的与卷积,与卷积的 $2^i$ 项之和即为答案。

    (子集卷积:$c$ 是 $a$ 和 $b$ 的子集卷积,当且仅当:$c[i]=sumlimits_{j|k=i,j&k=0}a[j] imes b[k]$ ,直观理解上等价于 $c[i]=sumlimits_{jin i}a[j] imes b[i-j]$ ,故称子集卷积)

    异或卷积和与卷积可以直接使用FWT计算。

    子集卷积的计算方法可以参考vfk集训队论文中提到的占位多项式法:

    $j|k=i,j&k=0$ 等价于 $j|k=i,|j|+|k|=|i|$ 。

    因此求 $c'[p][i]=sumlimits_{j|k=i,|j|+|k|=p}a[j] imes b[k]=sumlimits_{j|k=i,|j|+|k|=p}a'[|j|][j] imes b'[|k|][k]=sumlimits_{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
    " , ans);
    	return 0;
    }
    
  • 相关阅读:
    二叉搜索树的建树与遍历
    SpringBoot Mybatis 读写分离配置(山东数漫江湖)
    Spring注解概览(数漫江湖)
    Spring Cloud的基本认识和使用Spring Cloud的基本教程(山东数漫江湖)
    全面了解Nginx主要应用场景(数漫江湖)
    Spring boot集成RabbitMQ(山东数漫江湖)
    Spring 事务管理(山东数漫江湖)
    透彻理解Spring事务设计思想之手写实现(山东数漫江湖)
    Spring整合Quartz分布式调度(山东数漫江湖)
    Spring归纳小结(山东数漫江湖)
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/8495879.html
Copyright © 2011-2022 走看看