歌名 - 歌手
0:00

    【51nod 1824】染色游戏

    题目

    有 n 个红球, m 个蓝球,从中取出 x 个红球和 y 个蓝球排成一排的得分是 rx⋅by ,其中 r0=b0=1 。
    定义 f(t) 表示恰好取出 t 个球排成一排的所有可能局面的得分之和。
    两个局面相同,当且仅当这两排球的个数相等,且在对应列位置上的颜色都是相同的。
    小Q想知道,有多少 t (1≤t≤n+m) 使得 f(t) 是奇数,你能告诉他满足条件的 t2 之和吗?
    对于样例, f(1)=2,f(2)=5,f(3)=13,f(4)=28,f(5)=50,f(6)=60 ,答案是 $22+32=13 $。

    分析

    cty爆音通道 to 分治做法什么的看到我一脸懵逼
    于是只能打个FWT
    题目中的\(f(t)=\sum_{x+y=t}r_xb_yC_{t}^{x}\),这个不用多解释。
    然后考虑如何判断\(f(t)\)是否为奇数,
    因为只用判断奇偶,只用保留%2的结果。
    据说根据lucas定理得出,\(C_{n+m}^n\)为奇数,尤其尤其仅当\([x\ and\ y=0]\)
    于是
    原式得

    \[f(t)=\sum_{x+y=t}r_xb_y[x\ and\ y=0] \]

    \[=\sum_{x+y=t}r_xb_y[x\ or\ y=t] \]

    \[=\sum_{x\ or\ y=t}r_xb_y[x+y=t] \]

    \(bit(i)\)表示二进制下i的1的个数

    \[=\sum_{x\ or\ y=t}r_xb_y[bit(x)+bit(y)=bit(t)] \]

    然后考虑如何用FWT处理这个,
    我们让\(rr_{bit(i),i}=r_i,bb_{bit(i),i}=b_i,其余为0\)
    然后,对于\(rr_{bit(0-20)},bb_{bit(0-20)}\), 都做一次FWT,
    接着,对于\(f_{bit(t),i}=\sum_{bit(x)+bit(y)=bit(t)}rr_{bit(x)}bb_{bit(y)}\)
    最后UFWT。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <bitset>
    const int maxlongint=2147483647;
    const int mo=1e9+7;
    const int N=2200005;
    const int M=1<<8;
    using namespace std;
    #define sqr(x) (1ll*(x)*(x))
    int n,m,r[N],b[N],fn,bit[N];
    long long ans;
    int rr[23][N>>3],bb[23][N>>3],v[4],mi[10];
    int val(int i,int j)
    {
    	return (i<<3)+7-j;
    }
    void read(int *a,int n)
    {
    	for(int i=1;i<=n;i++)
    	{
    		char c=getchar();
    		for(;c<'0' || c>'9';c=getchar());
    		a[i]=c-'0';
    	}
    }
    void FWT(int *f)
    {
    	for(int len=1;len<=3;len++)
    		for(int i=0;i<fn>>3;i++)
    			f[i]^=(f[i]&v[len])>>(1<<(len-1));
    	for(int len=2;len<=fn>>3;len<<=1)
    	{
    		int half=len>>1;
    		for(int i=0;i<half;i++)
    			for(int j=i;j<fn>>3;j+=len) f[j+half]^=f[j];
    	}
    }
    int main()
    {
    	freopen("1824.in","r",stdin);
    	freopen("1824.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	fn=1<<21,v[1]=170,v[2]=204,v[3]=240;
    	mi[0]=1;
    	for(int i=1;i<=8;i++) mi[i]=mi[i-1]<<1;
    	for(int i=0;i<=fn;i++)
    		for(int x=i;x;x&=x-1,bit[i]++);
    	r[0]=b[0]=1;
    	read(r,n),read(b,m);
    	for(int i=0;i<fn>>3;i++)
    		for(int j=7;j>=0;j--) 
    			rr[bit[val(i,j)]][i]^=(r[val(i,j)]&1)*mi[j],bb[bit[val(i,j)]][i]^=(b[val(i,j)]&1)*mi[j];
    	for(int i=0;i<=20;i++) FWT(rr[i]),FWT(bb[i]);
    	for(int i=0;i<fn>>3;i++)
    	{
    		for(int k=20;k>=0;k--)
    		{
    			int tmp=0;
    			for(int j=0;j<=k;j++)
    				tmp^=bb[k-j][i]&rr[j][i];
    			rr[k][i]=tmp;
    		}
    	}
    	for(int i=0;i<=20;i++) FWT(rr[i]);
    	for(int i=0;i<fn>>3;i++)
    		for(int j=7;j>=0;j--)
    			if(val(i,j)<=n+m)
    				if(rr[bit[val(i,j)]][i]&mi[j]) ans+=sqr(val(i,j));
    	printf("%lld\n",ans);
    }
    
    posted @ 2018-05-28 12:10  无尽的蓝黄  阅读(215)  评论(0编辑  收藏  举报