• [ICPC2020济南L] Bit Sequence


    [ICPC2020济南L] Bit Sequence - 数位dp

    Description

    定义 (f(x)) 表示 (x) 二进制表示的 (1) 的数量。给你n个是0或者1的数,再给你一个 (L),问在区间 ([0,L]) 之间有多少个数 (x) 满足 (∀i∈[0,m−1],f(x+i) mod 2=a_i)

    Solution

    核心观察是,(x+i) 只会频繁影响 (a[0..6]),对于 (a[7..]) 的部分,最多只会发生一次进位

    这次进位的影响,只和第 (7) 位往上连着的 (1) 的个数有关

    数位 dp,设 (f[pos][lim][sum][cnt]) 表示从高到低处理到了第 pos 位(低位为 0)此时是否顶格,前面数位的和的奇偶性为 (sum),从第 (pos+1) 位往高走的连续 (1) 的个数的奇偶性为 (cnt)

    如果处理到了 (pos<7) 的状态,就转入一个暴力

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    int a[105], b[105], siz, f[105][2][2][2], m, l;
    
    int par(int x)
    {
        return __builtin_parity(x);
    }
    
    int calc(int lim, int sum, int cnt)
    {
        int ans = 0;
        int up = lim ? l % 128 : 127;
        for (int i = 0; i <= up; i++)
        {
            int flag = 1;
            for (int j = 0; j < m && flag; j++)
                if ((i + j < 128 && (par(i + j) ^ sum ^ a[j])) || (i + j >= 128 && (par(i + j) ^ sum ^ cnt ^ a[j])))
                    flag = 0;
            ans += flag;
        }
        return ans;
    }
    
    int dfs(int pos, int lim, int sum, int cnt)
    {
        int &ans = f[pos][lim][sum][cnt];
        if (~ans)
            return ans;
        ans = 0;
        if (pos < 7)
            ans = calc(lim, sum, cnt);
        else
            for (int i = 0; i <= (lim ? b[pos] : 1); i++)
                ans += dfs(pos - 1, lim && b[pos] == i, sum ^ i, i && (!cnt));
        return ans;
    }
    
    void generate_b()
    {
        siz = 0;
        int t = l;
        while (t)
        {
            b[siz++] = t & 1;
            t /= 2;
        }
    }
    
    void solve()
    {
        memset(f, -1, sizeof f);
        memset(a, 0, sizeof a);
        memset(b, 0, sizeof b);
        cin >> m >> l;
        for (int i = 0; i < m; i++)
            cin >> a[i];
        generate_b();
        cout << dfs(siz - 1, 1, 0, 0) << endl;
    }
    
    signed main()
    {
        int t;
        cin >> t;
        while (t--)
        {
            solve();
        }
    }
    
  • 相关阅读:
    3813: 奇数国|树状数组|欧拉函数
    利用Perlin nosie 完毕(PS 滤镜—— 分成云彩)
    Qt QImageReader 相似乎有bug
    android studio 更新Gradle版本号方法
    Junit测试
    POI导出
    Properties文件读取
    md5加密
    递归找出文件夹里面所有文件
    java FileReader/FileWriter读写文件
  • 原文地址:https://www.cnblogs.com/mollnn/p/14563127.html
Copyright © 2020-2023  润新知