【HDU】5743 Join The Future【dp】
来源:互联网 发布:淘宝网妹儿粑粑饵料 编辑:程序博客网 时间:2024/06/05 17:08
题目链接:Join The Future
并查集压缩相等的点,发现最多只会有20个大于1的联通块,状压dp即可
#include <bits/stdc++.h>using namespace std ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 42 ;const int mod = 1e9 + 7 ;char buf[1000000] ;int len ;int p[MAXN] , c[MAXN] ;int L[MAXN] , R[MAXN] , odd[MAXN] , even[MAXN] ;int dp[MAXN][MAXN][2] ;pair < int , int > nxt[MAXN][MAXN][2] ;int ans[MAXN] , tmp[MAXN] ;int rt[MAXN] , col[MAXN] ;int idx[MAXN] ;int use[MAXN] ;int n , m ;int T ;int F ( int x ) { if ( p[x] == x ) return x ; int res = F ( p[x] ) ; c[x] ^= c[p[x]] ; return p[x] = res ;}int upd ( int x , int y , int o , int n ) { if ( dp[y][x][o] == 0 ) return 0 ; int m = y - x ; for ( int i = x ; i <= y ; ++ i ) { tmp[i] = nxt[y][i][o].first ; o = nxt[y][i][o].second ; } return 1 ;}void up ( int ok ) { if ( !ok ) return ; for ( int i = 1 ; i <= n ; ++ i ) { if ( tmp[i] > ans[i] ) return ; if ( tmp[i] < ans[i] ) { for ( int j = 1 ; j <= n ; ++ j ) { ans[j] = tmp[j] ; } return ; } }}void add ( int x ) { if ( x / 10 ) add ( x / 10 ) ; buf[len ++] = x % 10 + '0' ;}void solve ( int Case ) { scanf ( "%d%d" , &n , &m ) ; for ( int i = 0 ; i <= n ; ++ i ) { p[i] = i ; c[i] = 0 ; use[i] = 0 ; } for ( int i = 1 ; i <= n ; ++ i ) { scanf ( "%d%d" , &L[i] , &R[i] ) ; int tmp = R[i] - L[i] + 1 ; odd[i] = tmp / 2 + ( tmp % 2 == 1 && R[i] % 2 == 1 ) ; even[i] = tmp / 2 + ( tmp % 2 == 1 && R[i] % 2 == 0 ) ; } for ( int i = 1 ; i <= n ; ++ i ) { for ( int j = 1 ; j <= n + 1 ; ++ j ) { dp[i][j][0] = dp[i][j][1] = 0 ; nxt[i][j][0] = make_pair ( mod , mod ) ; nxt[i][j][1] = make_pair ( mod , mod ) ; } } for ( int i = 1 ; i <= n ; ++ i ) { dp[i][i + 1][0] = 1 ; for ( int j = i ; j >= 1 ; -- j ) { dp[i][j][0] = ( 1LL * dp[i][j + 1][1] * odd[j] + 1LL * dp[i][j + 1][0] * even[j] ) % mod ; dp[i][j][1] = ( 1LL * dp[i][j + 1][0] * odd[j] + 1LL * dp[i][j + 1][1] * even[j] ) % mod ; } for ( int j = 1 ; j <= i ; ++ j ) { if ( dp[i][j + 1][1] && odd[j] ) { nxt[i][j][0] = min ( nxt[i][j][0] , make_pair ( L[j] + ( L[j] % 2 == 0 ) , 1 ) ) ; } if ( dp[i][j + 1][0] && even[j] ) { nxt[i][j][0] = min ( nxt[i][j][0] , make_pair ( L[j] + ( L[j] % 2 == 1 ) , 0 ) ) ; } if ( dp[i][j + 1][0] && odd[j] ) { nxt[i][j][1] = min ( nxt[i][j][1] , make_pair ( L[j] + ( L[j] % 2 == 0 ) , 0 ) ) ; } if ( dp[i][j + 1][1] && even[j] ) { nxt[i][j][1] = min ( nxt[i][j][1] , make_pair ( L[j] + ( L[j] % 2 == 1 ) , 1 ) ) ; } } } int ok = 1 ; for ( int i = 1 ; i <= m ; ++ i ) { int u , v , w , x , y ; scanf ( "%d%d%d" , &u , &v , &w ) ; -- u ; x = F ( u ) ; y = F ( v ) ; use[u] = use[v] = 1 ; if ( x != y ) { if ( x < y ) swap ( x , y ) ; p[x] = y ; c[x] = ( c[u] - c[v] + 2 + w ) % 2 ; } else if ( ( c[u] ^ c[v] ) != w ) ok = 0 ; } if ( !ok ) { buf[len ++] = '0' ; buf[len ++] = '\n' ; buf[len ++] = '-' ; buf[len ++] = '1' ; buf[len ++] = '\n' ; return ; } int cnt = 0 , tot = 0 ; for ( int i = 0 ; i <= n ; ++ i ) if ( use[i] ) { if ( F ( i ) == i ) rt[cnt ++] = i ; idx[tot ++] = i ; } int res = 0 , OK = 0 ; for ( int i = 1 ; i <= n ; ++ i ) { ans[i] = mod ; } for ( int s = 0 ; s < 1 << cnt ; ++ s ) { if ( cnt && rt[0] == 0 && s % 2 ) continue ; col[0] = 0 ; for ( int i = 0 ; i < cnt ; ++ i ) { col[rt[i]] = s >> i & 1 ; } int ans = 1 , j = 0 , ok = 1 ; for ( int o = ( rt[0] == 0 ) ; o < tot ; ++ o ) { int i = idx[o] , x = p[i] ; if ( x != i ) col[i] = col[x] ^ c[x] ^ c[i] ; ans = 1LL * ans * dp[i][j + 1][col[j] ^ col[i]] % mod ; ok &= upd ( j + 1 , i , col[j] ^ col[i] , j ) ; if ( !ok ) break ; j = i ; } if ( ok && j < n ) { ans = 1LL * ans * ( dp[n][j + 1][0] + dp[n][j + 1][1] ) % mod ; int a = upd ( j + 1 , n , 0 , j ) ; up ( ok && a ) ; int b = upd ( j + 1 , n , 1 , j ) ; up ( ok && b ) ; ok &= a | b ; } else up ( ok ) ; if ( ok ) OK = 1 ; res = ( res + ans ) % mod ; } if ( !OK ) { buf[len ++] = '0' ; buf[len ++] = '\n' ; buf[len ++] = '-' ; buf[len ++] = '1' ; buf[len ++] = '\n' ; } else { add ( res ) ; buf[len ++] = '\n' ; for ( int i = 1 ; i <= n ; ++ i ) { add ( ans[i] ) ; buf[len ++] = i < n ? ' ' : '\n' ; } }}int main () { //freopen ( "1010.in" , "r" , stdin ) ; //freopen ( "1010.txt" , "w" , stdout ) ; len = 0 ; scanf ( "%d" , &T ) ; for ( int i = 1 ; i <= T ; ++ i ) solve ( i ) ; buf[len] = 0 ; printf ( "%s" , buf ) ; return 0 ;}
0 0
- 【HDU】5743 Join The Future【dp】
- hdu 5743 Join The Future
- HDU 5743 Join The Future 给定部分区间和奇偶,和数字范围,求方案数 DP
- 【HDU5743 2016 Multi-University Training Contest 2J】【dfs展开式DP 前缀和思想】Join The Future 40个数已知区间和为奇或偶输出方案
- UVALive 6680 Join the Conversation (DP)
- The Future
- hdu 1355 The Peanuts(DP)
- hdu 1709 The Balance (dp)
- hdu 1561 The more, The Better DP
- The future of J2EE
- Bles for the future
- Modified in the future
- Wireless Communications: The Future
- maven2 is the future?
- The future of testing
- the future of JavaScript
- the road of future
- fighting for the future
- 10082
- android中网格布局组件溢出原因
- jQuery动画函数
- QT QPapint的使用
- Android 监听back事件,点击两次退出程序
- 【HDU】5743 Join The Future【dp】
- HDU-1003-Max Sum(DP)
- 顺序表应用6:有序顺序表查询
- linux中在 ls -l 命令下的含义
- jQuery简化DOM操作
- 压感断 容流通
- 怒斥互联网社交产品
- [李景山php]每天TP5-20161210|Config.php
- 【继承】----子父类成员变量--内存简单图解