51nod 1824(算法马拉松30)
嘻嘻嘻。感觉还是有进步的。再接再厉。
显然:
f(t)=∑x+y=trxby(tx)
组合解释就是确定其中一种颜色即可。
显然。直接 FFT 不可行。
但是。在 mod 2 意义下。
(tx)=[x xor y=t][x and y=0] (mod 2)(tx)=[x or t=t][x and y=0] (mod 2)
所以:
f(t)=(∑x+y=trxby(tx)) mod 2=∑x+y=t(rxby[x or y=t][x and y=0]) mod 2
因为卷积限制了 x+y=t
所以:
∑x+y=t(rxby[x or y=t]) mod 2=∑x or y=t(rxby[x+y=t]) mod 2=∑x or y=t(rxby[bit(x)+bit(y)=bit(t)]) mod 2
其中
bit(x)
位
x
二进制形式中1 的数量
之所以转换为 or 形式而不是用 xor 是因为 or 没有除法。(对应的快速沃尔什变换)
在 mod 2 意义下可以进一步的实用bitset优化。(手动实现。
且此时 FWT 等价于 FWT−
#include <algorithm>
#include <string.h>
#include <cmath>
#include <stdio.h>
#include <vector>
#define MAXN 4200000
using namespace std;
typedef long long LL;
int r[22][200000];
int b[22][200000];
int bit[MAXN];
int tmp1[30],tmp2[30];
char S1[MAXN];
char S2[MAXN];
int bb[7];
void FWT(int y[],int len)
{
int ll=(len>>5)+1;
for(int h=1;h<6;h++)
{
int s=(1<<(h-1));
for(int i=0;i<ll;i++) y[i]=(y[i]^((y[i]&bb[h])<<s));
}
for(int h=6;(1<<h)<=len;h++)
{
int H=1<<(h-5);
int s=(1<<(h-6));
for(int i=0,j=s;i<ll;i+=H,j+=H)
for(int L=i,R=j;L<j;L++,R++) y[R]^=y[L];
}
}
int main ()
{
int k=0;
while(k<16)
{
bb[1]=(bb[1]<<2)|1;
k++;
}
k=0;
while(k<8)
{
bb[2]=(bb[2]<<4)|3;
k++;
}
k=0;
while(k<4)
{
bb[3]=(bb[3]<<8)|0xf;
k++;
}
k=0;
while(k<2)
{
bb[4]=(bb[4]<<16)|0xff;
k++;
}
bb[5]=(0xffff);
for(int i=1;i<MAXN;i++)
if(i&1)
bit[i]=bit[i>>1]+1;
else
bit[i]=bit[i>>1];
int n,m;
scanf("%d %d",&n,&m);
scanf("%s",S1+1);
scanf("%s",S2+1);
r[0][0]=1;
b[0][0]=1;
for(int i=1;i<=n;i++) r[bit[i]][i>>5]|=((S1[i]-'0')&1)<<(i&31);
for(int i=1;i<=m;i++) b[bit[i]][i>>5]|=((S2[i]-'0')&1)<<(i&31);
int len=32;
while(len<(n+m+2))len<<=1;
for(int i=0;i<22;i++) FWT(r[i],len);
for(int i=0;i<22;i++) FWT(b[i],len);
for(int t=0;t<=(len>>5);t++)
{
for(int i=0;i<22;i++)
{
tmp1[i]=r[i][t];
r[i][t]=0;
}
for(int i=0;i<22;i++) tmp2[i]=b[i][t];
for(int k=0;k<22;k++)
for(int i=0;i<=k;i++)
r[k][t]^=tmp1[i]&tmp2[k-i];
}
for(int i=0;i<22;i++) FWT(r[i],len);
LL ans=0;
for(int t=1,s=m+n+1;t<s;t++)
{
int f=((r[bit[t]][t>>5])>>(t&31))&1;
if(f) ans+=(LL)t*t;
}
printf("%lld\n",ans);
return 0;
}