【bzoj3866】The Romantic Hero dp

题目描述

给你n个数,从中选出两个不相交非空集合S和T,使得S中的每一个元素都在T集合的前面,并且S集合中的所有数的亦或等于T集合中的所有数的与,求方案数 mod 10^9+7。

输入

The first line contains an integer T, denoting the number of the test cases.
For each test case, the first line contains a integers n.
The next line contains n integers a_1,a_2,...,a_n which are separated by a single space.
n<=10^3, 0 <= a_i <1024, T<=20.

输出

For each test case, output the result in one line.

样例输入

2
3
1 2 3
4
1 2 3 3

样例输出


4

题解:是一道dp常规题,思路很常规,但并不简单,特别是最后的去重,不细心的话很容易忽略就连样例都过不了。s【i】【j】表示前i位选出数^得到j的方案数,t【i】【j】表示后i位选数&得到j的方案数,最后通过乘法原理得出答案。,一定注意最后的ss【i】【0】--去重!!!

总结:dp很多题都是求前i个数……后i个数……,难点就是怎么讲前后连接,而求前i个数……、后i个数……通常都要枚举中间值k。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define N 30000
#define mod 1000000007
using namespace std;
int n,date[N],T;
int ss[1024][1024],st[1024][1024],fs[1024][1024],ft[1024][1024],ans;
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&date[i]);
		memset(ss,0,sizeof(ss));memset(st,0,sizeof(st));memset(fs,0,sizeof(fs));memset(ft,0,sizeof(ft));
		ss[0][0]=1;st[n+1][1023]=1;
		for(int i=1;i<=n;i++){
			for(int j=0;j<1024;j++) fs[i][j^date[i]]=(fs[i][j^date[i]]+ss[i-1][j])%mod;
			for(int j=0;j<1024;j++) ss[i][j]=(ss[i-1][j]+fs[i][j])%mod;
		}
		for(int i=n;i;i--){
			for(int j=0;j<1024;j++) ft[i][j&date[i]]=(ft[i][j&date[i]]+st[i+1][j])%mod;
		 	for(int j=0;j<1024;j++) st[i][j]=(st[i+1][j]+ft[i][j])%mod;
		}
		ans=0;
		for(int i=1;i<n;i++){
			ss[i][0]--;//!!!
			for(int j=0;j<1024;j++)
			    ans = ( ans + 1ll*ss[i][j]*ft[i+1][j] )%mod;
		}
		printf("%d\n",ans);		
	}
	return 0;
}
/*
2
3
1 2 3
4
1 2 3 3
*/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值