51nod 1824(算法马拉松30)

来源:互联网 发布:js从入门到精通 编辑:程序博客网 时间:2024/05/16 19:55

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 4200000using 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;}
原创粉丝点击