zoukankan      html  css  js  c++  java
  • BZOJ 5267 特工 (类FWT)

    题意

    题解

    从大到小枚举(l), 把一个序列从(2^{l+1})分成两个独立的(2^l),去除两半的影响。
    设去除前的序列为(b), 去除后序列为(b')
    则有(b_{2^{l+1}-1}-b_{2^l-1}=sum^{2^{l+1}-1}_{i=2^l}b_i)
    考虑左边的一个位置(d)与右边的位置(d+2^l)相对应
    考虑一个序列(s_0)的第(i)位为( ext{bitcount}((i ext{or} d) ext{xor} i))(s_1)为把(s_1)(d)换成(d+2^l)的结果
    显然两个序列左半部分完全一样,右半部分完全相反
    (z)(b')(s_0)(或(s_1))左半部分对应位置乘积之和,(y_0,y_1)分别为(b')(s_0,s_1)右半部分对应位置乘积之和
    (b'_d=z,b'_{d+2^l}=y_1)
    且有方程(z+y_0=b_d,z+y_1=b_{d+2^l},y_0+y_1=b_{2^{l+1}-1}-b_{2^l-1})
    解之即可。

    时间复杂度(O(nlog n)).

    代码

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cassert>
    #define llong long long
    using namespace std;
     
    char c[40000010];
    int ns;
    inline llong read(){
        while(c[ns]<'0'||c[ns]>'9')ns++;
        llong x=0;
        while(c[ns]>='0'&&c[ns]<='9')x=(x<<3)+(x<<1)+c[ns++]-'0';
        return x;
    }
     
    const int N = 1<<20;
    llong a[N+3];
    int n;
     
    int main()
    {
        c[fread(c,1,40000010,stdin)]=0; //input optimization
        n = read();
        for(int i=0; i<n; i++) a[i] = read();
        for(int i=(n>>1); i; i>>=1)
        {
            for(int j=0; j<n; j+=(i<<1))
            {
                llong tmp = a[j+(i<<1)-1]-a[j+i-1];
                for(int k=0; k<i; k++)
                {
                    llong x = a[j+k],y = a[j+i+k];
                    a[j+k] = (-tmp+x+y)>>1,a[j+i+k] = (tmp-x+y)>>1;
                }
            }
        }
        for(int i=0; i<n; i++) printf("%lld ",a[i]); puts("");
        return 0;
    }
    
  • 相关阅读:
    hdu1074Doing Homework
    1088滑雪
    hdu1078FatMouse and Cheese
    hdu1058Humble Numbers
    hdu1114 Piggy-Bank
    hdu1069Monkey and Banana
    未解决的问题_c#中,最小化触发事件
    WPF Button 样式资源设置&后台生成button样式
    .NET 调用外部exe程序,出现已停止工作
    json类序列化与反序列化参考
  • 原文地址:https://www.cnblogs.com/suncongbo/p/11616099.html
Copyright © 2011-2022 走看看