Don't Blame Me (dp问题)

发布时间 2023-06-01 20:35:53作者: xxj112

大意:有一个数组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> dp(n+1,vector((1<<6),0) ; 新建一个二维数组 dp[n+1][(1<<6)] 全部赋值为0;
代码:

点击查看代码
#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;
}