题目:http://codeforces.com/contest/914/problem/G

第一个括号可以子集卷积;第三个括号可以用 FWT 异或卷积;这样算出选两个数组成 x 的方案数;三个部分的方案数分别乘上 f[ x ] 再一起与卷积即可。

注意子集卷积的时候不要改 tp[ i ][ s ] ,因为要的是恰好两个数拼起来,没有改过的(但是做过 FMT 的) tp[ i ][ s ] 存的是初值,表示选 1 个数的方案数。

  所以如果可以选任意多个数,就可以像背包一样, tp[ j ][ s ] 用的改过的, tp[ i-j ][ s ] 用没改过的。

累计完 tp[ i ][ s ] 的时候,要在 i 这一层 iFMT 回去,再贡献给 a[ s ] ,不要直接加到 a[ s ] 上、做完所有的 i 之后再 iFMT 回去,因为 iFMT 只能弄回去对于同一个 i 的。

卷积的时候不要对 i - j == j 的情况去重,因为可以选重复的。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
int Mx(int a,int b){return a>b?a:b;}
const int K=,N=(<<K)+,mod=1e9+;
int f[N],a[N],b[N],c[N],bin[K+],len,bh;
int ct[N],tp[K+][N];
void upd(int &x){x>=mod?x-=mod:;}
void init()
{
bin[]=;for(int i=;i<=K;i++)bin[i]=bin[i-]<<;
for(int s=,j=bin[K];s<j;s++)ct[s]=ct[s-(s&-s)]+;
f[]=;f[]=;for(int i=,j=bin[K];i<j;i++)f[i]=f[i-]+f[i-],upd(f[i]);
}
void fwt_and(int *a,bool fx)
{
for(int R=;R<=len;R<<=)
for(int i=,m=R>>;i<len;i+=R)
for(int j=;j<m;j++)
a[i+j]+=(fx?mod-a[i+m+j]:a[i+m+j]),upd(a[i+j]);
}
void dv2(int &x){if(x&)x=(x+mod)>>; else x>>=;}
void fwt_xor(int *a,bool fx)
{
for(int R=;R<=len;R<<=)
for(int i=,m=R>>;i<len;i+=R)
for(int j=;j<m;j++)
{
int x=a[i+j],y=a[i+m+j];
a[i+j]=x+y; a[i+m+j]=x+mod-y;
upd(a[i+j]); upd(a[i+m+j]);
if(fx)dv2(a[i+j]),dv2(a[i+m+j]);
}
}
void fmt(int *a,bool fx)
{
for(int i=;i<len;i<<=)
for(int s=;s<len;s++)
if(s&i)a[s]+=(fx?mod-a[s^i]:a[s^i]),upd(a[s]);
}
void cz()
{
int t[N];
for(int i=;i<=bh;i++)fmt(tp[i],);//<= not <
for(int i=;i<=bh;i++)
{
for(int s=;s<len;s++)t[s]=;
for(int j=;j<=i;j++)
for(int s=;s<len;s++)
t[s]=(t[s]+(ll)tp[j][s]*tp[i-j][s])%mod;
fmt(t,);
for(int s=;s<len;s++)
if(i==ct[s])a[s]+=t[s],upd(a[s]);
}
/*
for(int i=0;i<=bh;i++)
{
for(int j=0;j<=i;j++)
for(int s=0;s<len;s++)
{
if(i!=ct[s])continue;//
a[s]=(a[s]+(ll)tp[j][s]*tp[i-j][s])%mod;//i-j==j is ok!
}
}
fmt(a,1);
*/
}
int main()
{
init();int n=rdn(),mx=;
for(int i=,d;i<=n;i++)
{
d=rdn();mx=Mx(mx,d);
tp[ct[d]][d]++;c[d]++;b[d]+=f[d];upd(b[d]);
}
for(bh=;bin[bh]<=mx;bh++);len=bin[bh];
cz();
fwt_xor(c,);for(int i=;i<len;i++)c[i]=(ll)c[i]*c[i]%mod;fwt_xor(c,);
for(int i=;i<len;i++)a[i]=(ll)a[i]*f[i]%mod;
for(int i=;i<len;i++)c[i]=(ll)c[i]*f[i]%mod;
fwt_and(a,); fwt_and(b,); fwt_and(c,);
for(int i=;i<len;i++)a[i]=(ll)a[i]*b[i]%mod*c[i]%mod;
fwt_and(a,);
int ans=;
for(int i=;i<len;i<<=)ans+=a[i],upd(ans);
printf("%d\n",ans);
return ;
}

CF 914G Sum the Fibonacci——子集卷积的更多相关文章

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

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

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

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

  3. CF914G Sum the Fibonacci (快速沃尔什变换FWT + 子集卷积)

    题面 题解 这是一道FWT和子集卷积的应用题. 我们先设 cnt[x] 表示 Si = x 的 i 的数量,那么 这里的Nab[x]指满足条件的 Sa|Sb=x.Sa&Sb=0 的(a,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. 【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 ...

  6. 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 | ...

  7. UOJ 348 【WC2018】州区划分——子集卷积

    题目:http://uoj.ac/problem/348 参考:https://www.cnblogs.com/NaVi-Awson/p/9242645.html#%E5%AD%90%E9%9B%86 ...

  8. UOJ #348 州区划分 —— 状压DP+子集卷积

    题目:http://uoj.ac/problem/348 一开始可以 3^n 子集DP,枚举一种状态的最后一个集合是什么来转移: 设 \( f[s] \) 表示 \( s \) 集合内的点都划分好了, ...

  9. UOJ348 WC2018 州区划分 状压DP、欧拉回路、子集卷积

    传送门 应该都会判欧拉回路吧(雾 考虑状压DP:设\(W_i\)表示集合\(i\)的点的权值和,\(route_i\)表示点集\(i\)的导出子图中是否存在欧拉回路,\(f_i\)表示前若干个城市包含 ...

随机推荐

  1. 20145328 《网络对抗技术》逆向及Bof基础实践

    20145328 <网络对抗技术>逆向及Bof基础实践 实践内容 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回 ...

  2. Python3基础 print \" 输出单引号与双引号

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  3. Linux的硬链接和软链接

    1.Linux链接概念Linux链接分两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link), 也就是软链接.默认情况下,ln命令产生硬链接. [硬连接]硬连 ...

  4. $.proxy用法详解

    jQuery中的$.proxy官方描述为: 描述:接受一个函数,然后返回一个新函数,并且这个新函数始终保持了特定的上下文语境. 官方API: jQuery.proxy( function, conte ...

  5. nodejs路由中:冒号

    路由必看的博客博客,也是学习node必看的博客:http://www.open-open.com/lib/view/open1409929982338.html 下面是一些路由例子,以及与之相匹配的关 ...

  6. 利用JS将页面中包含“一个”字段值的元素改为红色

    document.body.innerHTML = document.body.innerHTML.replace(/一个/ig,"<span style='color: red;'& ...

  7. cf812B 搜索

    B. Sagheer, the Hausmeister time limit per test 1 second memory limit per test 256 megabytes input s ...

  8. a标记无效问题

    当在<a href=''></a>这个标记中嵌入<td></td>  就会导致部分浏览器无法单击,所以在开发HTML页面的时候,一定不要在 a标记中嵌入 ...

  9. Android orm 框架xUtils简介

    数据库操作建议用ORM框架,简单高效.这里推荐xUtils,里面包含DBUtils.github地址:https://github.com/wyouflf/xUtils 获得数据库实例建议用单例模式. ...

  10. HDU 4751 Divide Groups (2-SAT)

    题意 给定一个有向图,问是否能够分成两个有向完全图. 思路 裸的2-sat--我们设一个完全图为0,另一个完全图为1,对于一个点对(u, v),如果u.v不是双向连通则它们两个不能在一组,即u和v至少 ...