【HDU】4901 The Romantic Hero 01背包

来源:互联网 发布:java log4j用法 编辑:程序博客网 时间:2024/06/06 00:16

传送门:【HDU】4901 The Romantic Hero


题目分析:这个01背包好做。。。。因为S集合一定在T集合的左边,那么可以枚举集合的分割线,并且枚举出的方案要保证没有重复。方案数可以通过01背包求出。如果要保证不重复,其实只要保证分割线上的点要强制被取到就行了。像我就是保证S集合的最右端一定要被取到,然后T集合是没有限制的。


代码如下:


#include <cstdio>#include <cstring>#include <algorithm>using namespace std ;#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define REV( i , a , b ) for ( int i = a - 1 ; i >= b ; -- i )#define FOV( i , a , b ) for ( int i = a ; i >= b ; -- i )#define CLR( a , x ) memset ( a , x , sizeof a )typedef long long LL ;const int MAXN = 1200 ;const int mod = 1e9 + 7 ;int num[MAXN] ;int f[MAXN][MAXN] , a[MAXN][MAXN] ;void solve () {int n ;scanf ( "%d" , &n ) ;FOR ( i , 1 , n )scanf ( "%d" , &num[i] ) ;CLR ( f , 0 ) ;f[0][0] = 1 ;FOR ( i , 1 , n ) {FOR ( v , 0 , 1024 ) {f[i][v] = f[i - 1][v] + f[i - 1][v ^ num[i]] ;if ( f[i][v] >= mod )f[i][v] -= mod ;}FOR ( v , 0 , 1024 )a[i][v] = f[i - 1][v ^ num[i]] ;}CLR ( f , 0 ) ;FOV ( i , n , 1 ) {FOR ( v , 0 , 1024 ) {f[i][v] += f[i + 1][v] ;f[i][v & num[i]] += f[i + 1][v] ;if ( f[i][v] >= mod )f[i][v] -= mod ;if ( f[i][v & num[i]] >= mod )f[i][v & num[i]] -= mod ;}f[i][num[i]] ++ ;}//FOV ( i , n , 1 )//FOV ( j , 3 , 0 )//printf ( "f[%d][%d] = %d\n" , i , j , f[i][j] ) ;int ans = 0 ;FOR ( i , 1 , n - 1 )FOR ( j , 0 , 1024 )ans = ( ans + ( LL ) a[i][j] * f[i + 1][j] ) % mod ;printf ( "%d\n" , ans ) ;}int main () {int T ;scanf ( "%d" , &T ) ;while ( T -- )solve () ;return 0 ;}


0 0
原创粉丝点击