• CF449D Jzzhu and Numbers


    给出一个长度为n的序列(a_1,a_2...a_n)。求构造出一个序列(i_1 le i_2 le ... le i_k(1le{k}le{n}))使得(a_{i_1}&a_{i_2}&...&a_{i_k}=0) 。求方案数模(10^9+7)

    也就是从({a_i}) 里面选出一个非空子集使这些数按位与起来为0.

    (nle 10^6,a_ile10^6)


    发现这个就是个与意义下的背包,然后考虑用 FWT 优化,我们每次加入一个物品之后会有两种选择,也就是会使其 ( imes2) ,那么用桶记录下 (i) 有多少个,然后 FWT 过去,这里的 (A_i) 就是每个位置上的翻倍的倍数了,算出来之后再 IFWT 回去就可以了。

    Code

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    const int N = 20;
    const int p = 1e9 + 7;
    using namespace std;
    int n,a[1 << N],t[1 << N],m2[1 << N];
    void FWT(int *a)
    {
        for (int i = 1;i < (1 << N);i <<= 1)
            for (int j = 0;j < (1 << N);j += i << 1)
                for (int k = 0;k < i;k++)
                {
                    int a0 = a[j + k],a1 = a[j + k + i];
                    a[j + k] = a1;
                    a[j + k + i] = (a0 + a1) % p;
                }
    }
    void IFWT(int *a)
    {
        for (int i = 1;i < (1 << N);i <<= 1)
            for (int j = 0;j < (1 << N);j += i << 1)
                for (int k = 0;k < i;k++)
                {
                    int a0 = a[j + k],a1 = a[j + k + i];
                    a[j + k] = (-a0 + a1) % p;
                    a[j + k + i] = a0;
                }
    }
    int main()
    {
        scanf("%d",&n);
        m2[0] = 1;
        for (int i = 1;i < (1 << N);i++)
            m2[i] = 2ll * m2[i - 1] % p;
        for (int i = 1;i <= n;i++)
        {
            scanf("%d",&a[i]);
            t[a[i]]++;
        }
        FWT(t);
        for (int i = 0;i < (1 << N);i++)
            t[i] = m2[t[i]];
        IFWT(t);
        cout<<(t[0] + p) % p<<endl;
        return 0;
    }
    
  • 相关阅读:
    最近邻插值
    tp类型自动转换和自动完成
    tp读取器和写入器
    tp模型和数据库操作方法
    tp数据库操作
    tp请求和响应
    tp配置+路由+基本操作
    git的常见操作方法
    php 检查该数组有重复值
    公众号的TOKEN配置PHP代码
  • 原文地址:https://www.cnblogs.com/sdlang/p/14295131.html
Copyright © 2020-2023  润新知