您的位置:首页 > 其它

【bzoj3866】The Romantic Hero dp

2017-10-16 20:44 225 查看
题目描述

给你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
,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
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: