CF914G Sum the Fibonacci(FWT,FST)

CF914G Sum the Fibonacci(FWT,FST)

Luogu

题解时间

一堆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();}
posted @ 2020-07-21 18:19  RikukiIX  阅读(178)  评论(0编辑  收藏  举报