题目大意:给定一个长为$n$($n\leq 10^6$)的序列S,定义一个合法的五元组$(a,b,c,d,e)$合法当且仅当

$$ ( S_a \mid S_b ) and S_c and ( S_d \bigotimes S_e ) = 2^k $$

$$ S_a and S_b = 0 $$

对于所有的合法的五元组,求 $ \sum_{合法(a,b,c,d,e)}\  F( S_a \mid S_b ) \times F( S_c ) \times F( S_d \bigotimes S_e ) $

其中$F(i)$表示斐波那契数列第i项  $F(1)=0,F(2)=1$

$S_i\leq 2^{17}$ ,答案对1e9+7取模。

先放一篇大佬的博客,我理解这道题的方式以及本文的思维方法都对该文略有参考。

https://blog.csdn.net/BeNoble_/article/details/79512236

看到这道题,看到应该想到对于一个五元组$(a,b,c,d,e)$,abcde具体的值并没有意义,真正有意义的是S中的值,所以我们不记录S[],而是记录t[]表示每个数的数量。

然后,我们显然可以把式子分成三个部分:

左侧   $j and k==0\bigcap j\mid k==i$ 意义下多项式的卷积

中间   多项式

右侧   $\sum_{[j\bigotimes k==i]}$ 意义下的卷积

合并之前,我们可以直接对每个部分的多项式的每个位置乘上对应的斐波那契序列值,然后合并,最后统计答案。

步骤:

1、求左侧部分的卷积

2、对中间部分赋值

3、求右侧部分的卷积

4、合并三个部分,枚举每一个2的k次方项累计答案

其中,步骤2最为简易,直接枚举数组位置一个接一个赋值就行,步骤3,4都可以用FWT即快速沃尔什(逆)变换解决,而第一步就需要一点智慧了(详见2015vfk集训队论文)。

我们将 j|k==i&&j&k==0 的条件转化为 $j|k==i$&&$|j|+|k|==|i|$,其中$|x|$表示x二进制下1的个数。于是,我们对于每一个$|x|$记录一个数组p,把原来的数$t[x]$放到$p[|x|][x]$中,然后对于每一层$|x|$进行$j|k==i$意义下的卷积。然后令$g[|x|][i]=\sum_{j+k=|x|} p[j][i] + p[k][i]$,再将每一层|x|进行一次逆变换,最后,对于每一个pos,将$g[|pos|][pos]$提出来乘以相应位置的斐波那契序列值形成一个新的数组,里面存的就是我们要的第一步的卷积了。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define mid (l+r>>1)
#define mod 1000000007ll
#define inv2 (mod+1>>1)
#define M 525000ll
#define OR 1ll
#define AND 2ll
#define XOR 3ll
using namespace std;
LL read(){
LL nm=0,fh=1;char cw=getchar();
for(;!isdigit(cw);cw=getchar()) if(cw=='-') fh=-fh;
for(;isdigit(cw);cw=getchar()) nm=nm*10+(cw-'0');
return nm*fh;
}
void write(LL x){
if(x<0){putchar('-');return write(-x);}
if(x>9) write(x/10);
putchar(x%10+'0');
} LL n,m,A[M],B[M],C[M],len,ans[M],bt[M],fib[M],maxn,top;
LL p[18][M],R[18][M],tt,t[M];
LL tk[M],h[M],w[M]; LL add(LL x,LL y){return (x+y+mod+mod)%mod;}
LL mul(LL x,LL y){return ((x*y%mod)+mod)%mod;}
void FWT(LL *x,LL tpe,LL kd){
for(LL tot=1;tot<len;tot<<=1){
for(LL st=0;st<len;st+=(tot<<1)){
for(LL pos=st;pos<st+tot;pos++){
LL t1=x[pos],t2=x[pos+tot];
if(tpe==OR) x[pos]=t1,x[pos+tot]=add(t1*kd,t2);
if(tpe==AND) x[pos]=add(t1,kd*t2),x[pos+tot]=t2;
if(tpe==XOR){
if(kd==1) x[pos]=add(t1,t2),x[pos+tot]=add(t1,-t2);
else x[pos]=mul(add(t1,t2),inv2),x[pos+tot]=mul(add(t1,-t2),inv2);
}
}
}
}
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
n=read(),fib[0]=0,fib[1]=1;
for(LL i=2;i<M;i++) fib[i]=add(fib[i-1],fib[i-2]);
//calculate fibonacci for(LL i=1;i<M;i++) bt[i]=bt[i-(i&-i)]+1;
//calculate Bit_count for(LL i=1;i<=n;i++) m=read(),t[m]++,maxn=max(maxn,m);
//Trun --> a1,a2,a3 into --> sumof(1) sumof(2)... at t[] for(len=1;len<=maxn;len<<=1) top++;
for(LL i=0;i<len;i++) h[i]=t[i],p[bt[i]][i]=t[i];
//create new array of t[] initialize p(i,j) for(LL i=0;i<=top;i++) FWT(p[i],OR,1ll);
for(LL i=0;i<=top;i++){
for(LL j=0;j+i<=top;j++){
for(LL pos=0;pos<len;pos++) R[i+j][pos]=add(R[i+j][pos],mul(p[i][pos],p[j][pos]));
}
}
for(LL i=0;i<=top;i++) FWT(R[i],OR,-1ll);
//GET p(i,j): Sigma Bitcount=i for(LL i=0;i<len;i++) B[i]=mul(t[i],fib[i]);
//GET Bi : fib[i]*t[i] FWT(h,XOR,1ll);
for(LL i=0;i<len;i++) C[i]=mul(h[i],h[i]);
FWT(C,XOR,-1ll);
for(LL i=0;i<len;i++) C[i]=mul(C[i],fib[i]);
//GET: Ci : fib[i]* ( Sgm j^k==i t[j]*t[k] ) for(LL i=0;i<len;i++) A[i]=mul(fib[i],R[bt[i]][i]);
//GET Ai : fib[i]* Sgm j|k==i&&|j|+|k|==|i| t[j]*t[k] FWT(A,AND,1ll),FWT(B,AND,1ll),FWT(C,AND,1ll);
//FWT to A,B,C for(LL i=0ll;i<len;i++) ans[i]=mul(A[i],mul(B[i],C[i]));
FWT(ans,AND,-1ll);
//FWT to A*B*C --> ans --> UFWT ans for(LL i=1ll;i<len;i<<=1) tt=add(tt,ans[i]);
write(tt);
//print answer return 0;
}

codeforces914G Sum the Fibonacci的更多相关文章

  1. Codeforces914G Sum the Fibonacci(FWT)

    FWT大杂烩.跟着模拟做很多次FWT即可. #include<iostream> #include<cstdio> #include<cmath> #include ...

  2. 【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 ...

  3. CF914G Sum the Fibonacci(FWT,FST)

    CF914G Sum the Fibonacci(FWT,FST) Luogu 题解时间 一堆FWT和FST缝合而来的丑陋产物. 对 $ cnt[s_{a}] $ 和 $ cnt[s_{b}] $ 求 ...

  4. 【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)\& ...

  5. Codecraft-18 and Codeforces Round #458 (Div. 1 + Div. 2, combined)G. Sum the Fibonacci

    题意:给一个数组s,求\(f(s_a | s_b) * f(s_c) * f(s_d \oplus s_e)\),f是斐波那契数列,而且要满足\(s_a\&s_b==0\),\((s_a | ...

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

    题目:http://codeforces.com/contest/914/problem/G 其实就是把各种都用子集卷积和FWT卷起来算即可: 注意乘 Fibonacci 数组的位置: 子集卷积时不能 ...

  7. 题解 CF914G Sum the Fibonacci

    题目传送门 题目大意 给出\(n,s_{1,2,...,n}\),定义一个五元组\((a,b,c,d,e)\)合法当且仅当: \[1\le a,b,c,d,e\le n \] \[(s_a\vee s ...

  8. CF914G Sum the Fibonacci FWT、子集卷积

    传送门 一道良心的练习FWT和子集卷积的板子-- 具体来说就是先把所有满足\(s_a \& s_b = 0\)的\(s_a \mid s_b\)的值用子集卷积算出来,将所有\(s_a \opl ...

  9. CF914G Sum the Fibonacci

    解:发现我们对a和b做一个集合卷积,对d和e做一个^FWT,然后把这三个全部对位乘上斐波那契数,然后做&FWT就行了. #include <bits/stdc++.h> , MO ...

随机推荐

  1. .Net 开发Windows Service

    1.首先创建一个Windows Service 2.创建完成后切换到代码视图,代码中默认有OnStart和OnStop方法执行服务开启和服务停止执行的操作,下面代码是详细解释: using Syste ...

  2. python 基础 9.12 索引

    #/usr/bin/python #-*- coding:utf-8 -*- #@Time   :2017/11/24 4:48 #@Auther :liuzhenchuan #@File   :索引 ...

  3. python模块, 包的初识

    Python 模块(Module), 是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句. 模块让你能够有逻辑地组织你的 Python 代码段. 把相关的代 ...

  4. [精]poj2724

    Purifying Machine Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5027   Accepted: 1455 ...

  5. Java程序发送邮件

    之前上网有看到过别人总结的使用java程序发送邮件,于是自己下来练习,把自己学习的一些心得总结出来. 首先我们这里需要采用两个jar包: 需要的朋友可以自行上网去CSDN类似的网站上面找 顺便把自己测 ...

  6. js判断undefined类型,undefined,null, 的区别详细解析

    js判断undefined类型 今天使用showModalDialog打开页面,返回值时.当打开的页面点击关闭按钮或直接点浏览器上的关闭则返回值是undefined所以自作聪明判断 var reVal ...

  7. nginx服务

    nginx服务 一.nginx安装 1.yum安装:yum  -y install nginx 注:centos 7中yum安装nginx前需要先安装 epel-release 2.源码包安装 安装之 ...

  8. 每天一个Linux命令(34)grep命令

          grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具 ...

  9. vim有用的快捷键

    多行前插入字符: ctrl + v (进入列模式,选上要插入的行) shift + i 输入要统一插入的字符 esc (虽然从外面看着是只有一行插入了,但是按下esc后就会发现之前选的都插入了 删除多 ...

  10. Python 3 udp 套接字

    Python 3 udp套接字 TCP是建立可靠连接,并且通信双方都可以以流的形式发送数据.相对TCP,UDP则是面向无连接的协议 使用UDP协议时,不需要建立连接,只需要知道对方的IP地址和端口号, ...