【bzoj3866】The Romantic Hero dp

来源:互联网 发布:网络爬虫用什么语言好 编辑:程序博客网 时间:2024/05/12 11:43

题目描述

给你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 1000000007using 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;}/*231 2 341 2 3 3*/