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 \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的更多相关文章
- Codeforces914G Sum the Fibonacci(FWT)
FWT大杂烩.跟着模拟做很多次FWT即可. #include<iostream> #include<cstdio> #include<cmath> #include ...
- 【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 ...
- CF914G Sum the Fibonacci(FWT,FST)
CF914G Sum the Fibonacci(FWT,FST) Luogu 题解时间 一堆FWT和FST缝合而来的丑陋产物. 对 $ cnt[s_{a}] $ 和 $ cnt[s_{b}] $ 求 ...
- 【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)\& ...
- 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 | ...
- CF 914 G Sum the Fibonacci —— 子集卷积,FWT
题目:http://codeforces.com/contest/914/problem/G 其实就是把各种都用子集卷积和FWT卷起来算即可: 注意乘 Fibonacci 数组的位置: 子集卷积时不能 ...
- 题解 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 ...
- CF914G Sum the Fibonacci FWT、子集卷积
传送门 一道良心的练习FWT和子集卷积的板子-- 具体来说就是先把所有满足\(s_a \& s_b = 0\)的\(s_a \mid s_b\)的值用子集卷积算出来,将所有\(s_a \opl ...
- CF914G Sum the Fibonacci
解:发现我们对a和b做一个集合卷积,对d和e做一个^FWT,然后把这三个全部对位乘上斐波那契数,然后做&FWT就行了. #include <bits/stdc++.h> , MO ...
随机推荐
- TextView实现打印机效果 ,字符串逐字显示
https://github.com/lygttpod/AndroidCustomView/blob/master/app/src/main/java/com/allen/androidcustomv ...
- 关于function的一种常用用法
关于function的一种常用用法 void Share::InitAcrossManager() { GsMgrEvent gsMgrEvents;//保存function的结构体 gsMgrEve ...
- Angular关于$anchorScroll的定位滚动
以下是实现定位滚动的代码: <!DOCTYPE html> <html lang="en" ng-app="app"> <head ...
- nginx日志自动切分
#!/bin/bash NGINX_LOG_PATH=/data/nginx-/logs # 昨天 YESTERDAY=$(date -d "yesterday" +%Y-%m-% ...
- Webpack探索【2】--- 安装、项目初始化、webpack.config.js配置文件
本文主要讲安装.项目初始化.webpack.config.js配置文件方面的内容.
- centos6.9下设置nginx服务开机自动启动
首先,在linux系统的/etc/init.d/目录下创建nginx文件,使用如下命令: vi /etc/init.d/nginx 在脚本中添加如下命令: #!/bin/sh # # nginx - ...
- spring 注入属性
一.注入对象类型的数据 1.配置文件 User类与UserService类均需要创建对象.所以都配置其相应的bean类,另外user需作为userService的属性注入,所以userService需 ...
- go语言之接口二
接口查询: 先来看如下的结构.结构体File实现了Read,Writer,Seek,Close的方法 type File struct{ } func (f *File) Read(buf []byt ...
- java基础入门1到100的奇数求和
/* Name:1-100所有奇数求和的程序 Power by Stuart Date:2015-4-23 */ public class DateTest01{ public static void ...
- 通过设置PHPSESSID保存到cookie实现免登录
$cookieParams = session_get_cookie_params(); session_set_cookie_params( 3600,// 设置sessionID在cookie中保 ...