【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 ,答案是 $2^2+3^2=13 \(。 ##分析 [cty爆音通道 to 分治做法](http://blog.csdn.net/alan_cty/article/details/78480332)什么的看到我一脸懵逼 于是只能打个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);
}

猜你喜欢

转载自www.cnblogs.com/chen1352/p/9099487.html