CF914G Sum the Fibonacci(FWT,FST)
阿新 • • 發佈:2020-07-21
CF914G Sum the Fibonacci(FWT,FST)
題解時間
一堆FWT和FST縫合而來的醜陋產物。
對 $ cnt[s_{a}] $ 和 $ cnt[s_{b}] $ 求FST,對 $ cnt[s_{d}] $ 和 $ cnt[s_{e}] $ 求異或卷積,然後對 $ cnt[ s_{ a }| s_{ b } ] \times f[ s_{ a }| s_{ b } ] $ , $ cnt[ s_{ c } ] \times f[ s_{ c } ] $ , $ cnt[ s_{ d } \oplus s_{ e } ] \times f[ s_{ d } \oplus s_{ e } ] $ 求與卷積,將每個 $ 2^{i} $ 項的答案加起來就完事。
#include<bits/stdc++.h> using namespace std; typedef long long lint; struct pat{int x,y;pat(int x=0,int y=0):x(x),y(y){}bool operator<(const pat &p)const{return x==p.x?y<p.y:x<p.x;}}; template<typename TP>inline void read(TP &tar) { TP ret=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){ret=ret*10+(ch-'0');ch=getchar();} tar=ret*f; } namespace RKK { const int N=18,S=1<<17; const int mo=1000000007,inv2=500000004; int bcnt(int x){return __builtin_popcount(x);} int lbit(int x){return __builtin_ffs(x);} int add(int a,const int &b){a+=b;if(a>=mo) a-=mo;else if(a<0) a+=mo;return a;} void doadd(int &a,const int &b){a+=b;if(a>=mo) a-=mo;else if(a<0) a+=mo;} void fwtand(int *a,int len,int tp) { for(int i=1;i<len;i<<=1)for(int j=0;j<len;j+=i<<1)for(int k=0;k<i;k++) doadd(a[j+k],tp*a[j+k+i]); } void fwtor(int *a,int len,int tp) { for(int i=1;i<len;i<<=1)for(int j=0;j<len;j+=i<<1)for(int k=0;k<i;k++) doadd(a[j+k+i],tp*a[j+k]); } void fwtxor(int *a,int len,int tp) { int x,y; for(int i=1;i<len;i<<=1)for(int j=0;j<len;j+=i<<1)for(int k=0;k<i;k++) { x=a[j+k],y=a[j+k+i]; a[j+k]=add(x,y),a[j+k+i]=add(x,-y); if(tp==-1) a[j+k]=(lint)a[j+k]*inv2%mo,a[j+k+i]=(lint)a[j+k+i]*inv2%mo; } } int n,mxlen=1,mxlog,mxa,bc[S]; int f[N][S],g[S]; int a[S],b[S],c[S],fib[S]; int main() { fib[0]=0,fib[1]=1;for(int i=2;i<S;i++) fib[i]=add(fib[i-1],fib[i-2]); for(int i=1;i<S;i++) bc[i]=bcnt(i); read(n);for(int i=1,w;i<=n;i++) read(w),mxa=max(mxa,w),f[bc[w]][w]++,a[w]++,doadd(b[w],fib[w]); while(mxlen<=mxa) mxlen<<=1,mxlog++; for(int i=0;i<=mxlog;i++) fwtor(f[i],mxlen,1); for(int i=0;i<=mxlog;i++) { memset(g,0,mxlen*4); for(int j=0;j<=i;j++)for(int s=0;s<mxlen;s++) doadd(g[s],1ll*f[j][s]*f[i-j][s]%mo); fwtor(g,mxlen,-1); for(int s=0;s<mxlen;s++)if(bc[s]==i) doadd(c[s],g[s]); } fwtxor(a,mxlen,1);for(int i=0;i<mxlen;i++) a[i]=1ll*a[i]*a[i]%mo;fwtxor(a,mxlen,-1); for(int i=0;i<mxlen;i++) a[i]=1ll*a[i]*fib[i]%mo; for(int i=0;i<mxlen;i++) c[i]=1ll*c[i]*fib[i]%mo; fwtand(a,mxlen,1),fwtand(b,mxlen,1),fwtand(c,mxlen,1);for(int i=0;i<mxlen;i++) c[i]=1ll*a[i]*b[i]%mo*c[i]%mo;fwtand(c,mxlen,-1); int ans=0;for(int i=1;i<mxlen;i<<=1) doadd(ans,c[i]); printf("%d\n",ans); return 0; } } int main(){return RKK::main();}