Codeforces 914G Sum the Fibonacci
2018-02-02 19:47
351 查看
题意
给出长度为nn的数组sisi,对于所有满足下列限制的五元组(a,b,c,d,e)(a,b,c,d,e)1. 1 ≤a, b, c, d, e ≤ n1 ≤a, b, c, d, e ≤ n
2. (sa|sb)(sa|sb) &scsc & (sd(sd^se) = 2ise) = 2i for some integer i
3. sasa&sb = 0sb = 0
求∑fib(sa|sb) ∗ fib(sc) ∗ fib(sd∑fib(sa|sb) ∗ fib(sc) ∗ fib(sd^se)se)。fibifibi是斐波那契数列的第ii项。
1≤n≤106,0≤si<2171≤n≤106,0≤si<217
分析
这题要用到子集卷积和FWT,都完美触及到我的知识盲区,在网上查了点资料,打算写篇博客记录一下。首先注意到max(n)>max(si)max(n)>max(si),所以可以考虑用axax表示有axax个sisi等于xx。
那么原问题大概可以通过以下步骤解决:
1.求AA数组使得Ai=fibi∗∑j∑k[j|k==iAi=fibi∗∑j∑k[j|k==i&&j∩k==∅]∗aj∗akj∩k==∅]∗aj∗ak
2.求BB数组使得Bi=fibi∗aiBi=fibi∗ai
3.求CC数组使得Ci=fibi∗∑j∑k[jCi=fibi∗∑j∑k[j^k==i]∗aj∗akk==i]∗aj∗ak
4.求DD数组使得Di=∑j∑k[jDi=∑j∑k[j&k==i]∗Aj∗Bkk==i]∗Aj∗Bk
5.求EE数组使得Ei=∑j∑k[jEi=∑j∑k[j&k==i]∗Dj∗Ckk==i]∗Dj∗Ck
1是子集卷积,345都可以FWTFWT搞搞。
子集卷积直接做有一种O(3n)O(3n)的做法,于是去学习了一下O(n2∗2n)O(n2∗2n)的姿势。不过网上貌似没有很多我看的懂的资料。查了很久查到了讲集合并卷积的东西。。仔细想了一下可能做法差不多。。?
集合并卷积是求fi=∑j∑k[j|k==i]∗aj∗akfi=∑j∑k[j|k==i]∗aj∗ak,也就是两个子集交集可以不为空。
考虑这样一个二维上的问题:求fi=∑max(r1,c1)==i∑max(r2,c2)==iar1,c1∗ar2,c2fi=∑max(r1,c1)==i∑max(r2,c2)==iar1,c1∗ar2,c2
有一种做法是求一次二维前缀和后,将前缀和自己做一次点积,然后沿着对角线做差分就是答案。
对应到求集合并卷积可能也是差不多的道理(强行意念差不多)。做一次高维前缀和之后点积一下然后高维差分就是答案。
子集卷积实际上就是把集合大小相同的集合都放在了一起,每种集合大小都各自跑集合并卷积,点积的时候把不同集合大小的卷起来就行。。
FWTFWT的证明YYYY了好久。。最后xjbxjb想了一下假装自己会了。。
for(int d=1;d<n;d<<=1)for(i=0;i<n;i+=d*2)for(j=0;j<d;++j){ //x=a[i+j],y=a[i+j+d] //正变换 //and a[i+j]=x+y //or a[i+j+d]=x+y //xor a[i+j]=x+y,a[i+j+d]=x-y //逆变换 //and a[i+j]=x-y //or a[i+j+d]=y-x //xor a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2 }
对于andand,考虑新增的位,f0f0和f1f1都被加到f′0f0′上,也就是f′0=f0+f1,f′1=f1f0′=f0+f1,f1′=f1,点积之后就是
h0=f′0∗g′0=(f0+f1)∗(g0+g1)=f0∗g0+f0∗g1+f1∗g0+f1∗g1h0=f0′∗g0′=(f0+f1)∗(g0+g1)=f0∗g0+f0∗g1+f1∗g0+f1∗g1
h1=f′1∗g′1=f1∗g1h1=f1′∗g1′=f1∗g1
显然h0h0多了一项f1∗g1f1∗g1,因为11&1==11==1,而这一项恰好等于h1h1,在逆变换中减去即可。将每一位多出的答案依次减掉之后最后就是所求。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=1<<17; const int MOD=1000*1000*1000+7; int n,inv2,a ,fib ,bits ,b[18] ,c[18] ,A ,B ,C ; inline void read(int&x){char c;while((c=getchar())<'0'||c>'9');x=c-'0';while((c=getchar())>='0'&&c<='9')x=x*10+c-'0';} inline void add(int&x,int y){x=x+y<MOD?x+y:x+y-MOD;} inline int he(int x,int y){return x+y<MOD?x+y:x+y-MOD;} int Pow(int x,int y){int t=1;for(;y;y>>=1,x=1LL*x*x%MOD)if(y&1)t=1LL*t*x%MOD;return t;} int main(){ int i,j,d,S; read(n); inv2=Pow(2,MOD-2); for(i=1;i<=n;++i)read(j),++a[j]; for(fib[1]=1,i=2;i<N;++i)fib[i]=he(fib[i-1],fib[i-2]); for(i=1;i<N;++i)bits[i]=bits[i>>1]+(i&1); for(i=0;i<N;++i)b[bits[i]][i]=a[i]; for(i=0;i<18;++i){ for(j=0;j<17;++j) for(S=0;S<N;++S)if(1<<j&S){ add(b[i][S],b[i][S^(1<<j)]); } } for(i=0;i<18;++i){ for(j=0;j<=i;++j){ for(S=0;S<N;++S){ add(c[i][S],1LL*b[j][S]*b[i-j][S]%MOD); } } } for(i=0;i<18;++i){ for(j=0;j<17;++j){ for(S=1;S<N;++S)if(1<<j&S){ add(c[i][S],MOD-c[i][S^(1<<j)]); } } } for(i=0;i<N;++i)A[i]=1LL*c[bits[i]][i]*fib[i]%MOD; for(i=0;i<N;++i)B[i]=1LL*a[i]*fib[i]%MOD,C[i]=a[i]; for(d=1;d<N;d<<=1){ for(i=0;i<N;i+=(d<<1)){ for(j=0;j<d;++j){ add(A[i+j],A[i+j+d]); add(B[i+j],B[i+j+d]); int x=C[i+j],y=C[i+j+d]; C[i+j]=he(x,y); C[i+j+d]=he(x,MOD-y); } } } for(i=0;i<N;++i)A[i]=1LL*A[i]*B[i]%MOD,C[i]=1LL*C[i]*C[i]%MOD; for(d=1;d<N;d<<=1){ for(i=0;i<N;i+=(d<<1)){ for(j=0;j<d;++j){ add(A[i+j],MOD-A[i+j+d]); int x=C[i+j],y=C[i+j+d]; C[i+j]=1LL*(x+y)*inv2%MOD; C[i+j+d]=1LL*(x-y+MOD)*inv2%MOD; } } } for(i=0;i<N;++i)C[i]=1LL*C[i]*fib[i]%MOD; for(d=1;d<N;d<<=1){ for(i=0;i<N;i+=(d<<1)){ for(j=0;j<d;++j){ add(A[i+j],A[i+j+d]); add(C[i+j],C[i+j+d]); } } } for(i=0;i<N;++i)A[i]=1LL*A[i]*C[i]%MOD; for(d=1;d<N;d<<=1){ for(i=0;i<N;i+=(d<<1)){ for(j=0;j<d;++j){ add(A[i+j],MOD-A[i+j+d]); } } } int ans=0; for(i=0;i<17;++i)add(ans,A[1<<i]); printf("%d\n",ans); return 0; }
相关文章推荐
- 【CF914G】Sum the Fibonacci 快速??变换模板
- Write a program to print the fibonacci series sum upto a particular no. using recursion.
- codeforces 213div(2) 365 A.Good Number 365 B.The Fibonacci Segment
- codeforces 213B div2 The Fibonacci Segment
- UVA 10236 The Fibonacci Primes
- codeforces 276 C. Little Girl and Maximum Sum
- CodeForces 29D Ant on the Tree
- Codeforces 250 E. The Child and Binary Tree [多项式开根 生成函数]
- HDOJ2058 The sum problem
- 【CodeForces】716B - Complete the Word(暴力)
- codeforces#277.5 C. Given Length and Sum of Digits
- codeforces 842 A. Kirill And The Game(阅读题)
- Codeforces 842 C. Ilya And The Tree (dfs)
- Codeforces 842C Ilya And The Tree
- The Union of k-Segments CodeForces - 612D (思维)
- codeforces 289 B. Polo the Penguin and Matrix
- The partial sum problem
- codeforces 27E Number With The Given Amount Of Divisors
- CodeForces 633 D.Fibonacci-ish(枚举)
- codeforces 266B(Queue at the School) Java