1 条题解

  • 1
    @ 2023-8-23 20:23:40

    题意:

    给定一个长度为 nn 的数组,选择它的一个子序列(不一定要连续的),问有多少种选法使得它们 AND 的值的二进制表示法中有 kk11

    思路:

    这个题就是一个简单的 DP,

    fi,jf_{i,j} 表示选择到了第 ii 个数字(但不一定是把前 ii 个数字都选择了),所有被选择的数字的 AND 值等于 jj 的方案数。

    那么我可以不选择这个数字:fi,j=fi,j+fi1,jf_{i,j} = f_{i,j} + f_{i-1,j},即与选择 i1i - 1 个数字,数字的 AND 的值为 jj 的方案数一样。

    那么我们也可以选择这个数字:fi,j&ai=fi,j&ai+fi1,jf_{i,j\& a_i} = f_{i,j\& a_i} + f_{i - 1,j},即从前 i1i - 1 个数得到的 jj 与上一个 aia_i 就有前 ii 个数字得到的 j&aij\&a_i

    当然,我们为什么一定要让第 ii 个数字受到前面的数字的影响呢?我们可以另起炉灶!即 fi,ai=1f_{i, a_i}=1

    这就讨论完了所有情况。

    归纳总结起来就是

    $$\begin{cases} f_{i,j} = f_{i,j} + f_{i-1,j} \\ f_{i,j\& a_i} = f_{i,j\& a_i} + f_{i - 1,j} \\ f_{i, a_i}=1 \\ \end{cases} $$

    代码:

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 200010, mod = 1e9 + 7;
    
    int f[N][64];
    int n, k;
    int a[N];
    
    void solve() {
        cin >> n >> k;
        for (int i = 1; i <= n; i++) memset(f[i], 0, sizeof(f[i]));
        for (int i = 1; i <= n; i++) cin >> a[i];
        for (int i = 1; i <= n; i++) {
            f[i][a[i]] = 1;
            for (int j = 0; j < 64; j++) {
                f[i][j] = (1ll * f[i][j] + f[i - 1][j]) % mod;
                f[i][j & a[i]] = (1ll * f[i][j & a[i]] + f[i - 1][j]) % mod;
            }
        }
        int res = 0;
        for (int i = 0; i < 64; i++) {
            int cnt = 0;
            for (int j = 0; j < 6; j++) {
                if (i >> j & 1) cnt++;
            }
            if (cnt == k) res = (1ll * res + f[n][i]) % mod;
        }
        cout << res << '\n';
    }
    
    int main() {
        #ifdef DEBUG
        freopen("Test.in", "r", stdin);
        cout << "===================START===================" << endl;
        #endif
    
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        int T;
        cin >> T;
        while (T--) solve();
    
        #ifdef DEBUG
        cout << "====================END====================" << endl;
        #endif
        return 0;
    }
    
    • 1

    信息

    ID
    8737
    时间
    2000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者