【ZOJ】3494 BCD Code AC自动机+数位DP

来源:互联网 发布:淘宝差评追评吗 编辑:程序博客网 时间:2024/04/30 13:47

传送门:【ZOJ】3494 BCD Code


题目分析:用AC自动机预处理出从一个状态的一个数转移到下一个数时的状态,然后就可以用数位DP解决了。现在看来这题也水水的。。


代码如下:


#include <cstdio>#include <cstring>#include <algorithm>using namespace std ;#define rep( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )#define rev( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )#define For( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )#define clr( a , x ) memset ( a , x , sizeof a )const int MAXN = 2005 ;const int mod = 1e9 + 9 ;struct ac_automaton {int next[MAXN][2] ;int fail[MAXN] ;int word[MAXN] ;int cur ;int root ;int Q[MAXN] ;int head ;int tail ;int newnode () {rep ( i , 0 , 2 ) next[cur][i] = -1 ;word[cur] = 0 ;return cur ++ ;}void init () {cur = 0 ;root = newnode () ;}void insert ( char buf[] ) {int now = root ;for ( int i = 0 ; buf[i] ; ++ i ) {int x = buf[i] - '0' ;if ( next[now][x] == -1 ) next[now][x] = newnode () ;now = next[now][x] ;}word[now] = 1 ;}void build () {head = tail = 0 ;fail[root] = root ;rep ( i , 0 , 2 ) {if ( ~next[root][i] ) {fail[next[root][i]] = root ;Q[tail ++] = next[root][i] ;} else next[root][i] = root ;}while ( head != tail ) {int now = Q[head ++] ;word[now] |= word[fail[now]] ;rep ( i , 0 , 2 ) {if ( ~next[now][i] ) {fail[next[now][i]] = next[fail[now]][i] ;Q[tail ++] = next[now][i] ;} else next[now][i] = next[fail[now]][i] ;}}}} ;ac_automaton ac ;int digit[MAXN] ;char buf[MAXN] ;int bcd[MAXN][10] ;int dp[MAXN][MAXN] ;int n ;int get_next ( int now , int x ) {if ( ac.word[now] ) return -1 ;rev ( i , 3 , 0 ) {if ( ac.word[ac.next[now][( x >> i ) & 1]] ) return -1 ;now = ac.next[now][( x >> i ) & 1] ;}return now ;}int dfs ( int cur , int s , int limit , int pre_zero ) {if ( cur == -1 ) return 1 ;if ( !limit && dp[cur][s] != -1 ) return dp[cur][s] ;int ans = 0 , n = limit ? digit[cur] : 9 ;if ( pre_zero ) {ans += dfs ( cur - 1 , s , limit && digit[cur] == 0 , 1 ) ;if ( ans >= mod ) ans -= mod ;} else if ( ~bcd[s][0] ) {ans += dfs ( cur - 1 , bcd[s][0] , limit && digit[cur] == 0 , 0 ) ;if ( ans >= mod ) ans -= mod ;}For ( i , 1 , n ) if ( ~bcd[s][i] ) {ans += dfs ( cur - 1 , bcd[s][i] , limit && n == i , 0 ) ;if ( ans >= mod ) ans -= mod ;}if ( !limit && !pre_zero ) dp[cur][s] = ans ;return ans ;}int deal ( char buf[] , int len ) {rep ( i , 0 , len ) digit[i] = buf[len - i - 1] - '0' ;return dfs ( len - 1 , 0 , 1 , 1 ) ;}void solve () {int ans = 0 ;ac.init () ;clr ( dp , -1 ) ;scanf ( "%d" , &n ) ;For ( i , 1 , n ) {scanf ( "%s" , buf ) ;ac.insert ( buf ) ;}ac.build () ;rep ( i , 0 , ac.cur ) rep ( j , 0 , 10 ) bcd[i][j] = get_next ( i , j ) ;scanf ( "%s" , buf ) ;int len1 = strlen ( buf ) ;rev ( i , len1 - 1 , 0 ) {if ( buf[i] > '0' ) {-- buf[i] ;break ;} else buf[i] = '9' ;}ans -= deal ( buf , len1 ) ;scanf ( "%s" , buf ) ;int len2 = strlen ( buf ) ;ans += deal ( buf , len2 ) ;if ( ans < 0 ) ans += mod ;printf ( "%d\n" , ans ) ;}int main () {int T ;scanf ( "%d" , &T ) ;while ( T -- ) solve () ;return 0 ;}


0 0
原创粉丝点击