H. Don’t Blame Me’
题意:
给一个数组,在其中找按位与和等于k的子序列,求子序列的个数mod 1e9 + 7。
思路:
动态规划,设f[i][j]表示在前i个数里面选,按位与和为j的子序列个数。
不选a[i]: f[i][j] = (f[i][j] + f[i - 1][j]) % mod;
选a[i]: f[i][j & a[i]] = (f[i][j & a[i]] + f[i - 1][j]) % mod;
代码:
/*************************************************************************
> File Name: h.cpp
> Author: Beans
> Mail: 3112748286@qq.com
> Created Time: 2023/5/24 12:39:48
************************************************************************/
#include <iostream>
#include <algorithm>
#include <cstring>
#define int long long
#define endl '\n'
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 3e5 + 7;
int n, k;
int a[maxn];
int f[maxn][70];
void solve(){
cin >> n >> k;
for(int i = 1; i <= n; i ++ ) cin >> a[i];
for(int i = 1; i <= n; i ++ ) memset(f[i], 0, sizeof f[i]);
for(int i = 1; i <= n; i ++ ){
f[i][a[i]] = 1;
for(int j = 0; j < 64; j ++ ){
f[i][j] = (f[i][j] + f[i - 1][j]) % mod;
f[i][j & a[i]] = (f[i][j & a[i]] + f[i - 1][j]) % mod;
}
}
int ans = 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) ans = (ans + f[n][i]) % mod;
}
cout << ans << endl;
}
signed main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while(t -- )
solve();
}