大意:有一个数组a,其中a[i]<64, 问你子序列中异或值中1的个数为k的子序列个数
题解:由于数组a的值很小异或后也很小 ,所以可以暴力dp
公式 :dp[i][j]//表示 前i个数中异或值为 j的子序列个数
dp[i][a[i]&j]=dp[i-1][j]+dp[i][a[i]&j];
核心:每次遍历当前a[i] 与0~(1<<6)异或值的大小 ,更新dp数组,a[i]&j的值可以来自,一定来自前面 为j的子序列。
另外 更新之选当前值
新知识: __buidtin_popcount(x) 表示 x二进制中一的个数
vector<vector
代码:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PLL;
#define IOS cin.tie(nullptr)->sync_with_stdio(false);
#define se second
#define mem(a,b) memset(a,b,sizeof a);
#define pri priority_queue<int,vector<int>,greater<int> >
#define low(a,b,c) lower_bound(a,a+b,c)-a;
#define upp(a,b,c) upper_bound(a,a+b,c)-a;
//const int N=1e6+7;
LL mod = (int)1e9 + 7;
void solve()
{
int n,x;
cin>>n>>x;
vector<LL> a(n+1);
vector<vector<LL> > dp(n+1,vector<LL>(1<<6,0) ) ;
for(int i=1;i<=n;i++)
{
cin>>a[i];
for(int j=0;j<(1<<6);j++){
dp[i][j]=dp[i-1][j];
dp[i][j&a[i]]+=dp[i-1][j];
dp[i][j&a[i]]%=mod;
}
dp[i][a[i]]+=1;
}
LL ans=0;
for(int i=0;i<(1<<6);i++)
{
if(__builtin_popcount(i)==x)
{
ans=(ans+dp[n][i])%mod;
}
}
cout<<ans<<"\n";
}
signed main()
{
IOS;
int t=1;
cin>>t;
while(t--)
{
solve();
}
return 0;
}