bzoj 3668 数位DP
收获:
1、如果有很多位操作,并且不包含+-×/等高级运算,那么可以一位一位考虑,如果求一个最优解,可以尝试逐位确定,这道题因为原始攻击值有范围,那么就需要数位DP。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /************************************************************** 2 Problem: 3668 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:288 ms 7 Memory:804 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #define max(a,b) ((a)>(b)?(a):(b)) 12 13 int n, m; 14 unsigned past[32][2]; 15 unsigned dp[32][2], top[32]; 16 17 int main() { 18 scanf( "%d%d", &n, &m ); 19 for( int i=0; i<32; i++ ) { 20 past[i][0] = 0; 21 past[i][1] = 1; 22 } 23 for( int i=1; i<=n; i++ ) { 24 char ch[10]; 25 unsigned t; 26 scanf( "%s%d", ch, &t ); 27 for( int b=0; b<32; b++ ) { 28 if( ch[0]=='A' ) { 29 past[b][0] &= (t>>b)&1; 30 past[b][1] &= (t>>b)&1; 31 } else if( ch[0]=='O' ) { 32 past[b][0] |= (t>>b)&1; 33 past[b][1] |= (t>>b)&1; 34 } else { 35 past[b][0] ^= (t>>b)&1; 36 past[b][1] ^= (t>>b)&1; 37 } 38 } 39 } 40 if( m==0 ) { 41 unsigned ans = 0; 42 for( int i=0; i<32; i++ ) 43 ans |= past[i][0]<<i; 44 printf( "%u\n", ans ); 45 } else { 46 for( int b=0; b<32; b++ ) 47 top[b] = (m>>b)&1; 48 49 int maxb=30; 50 while( top[maxb]==0 ) { 51 dp[maxb][1] = dp[maxb][0] = dp[maxb+1][1]|(past[maxb][0]<<maxb); 52 maxb--; 53 } 54 dp[maxb][1] = dp[maxb+1][1]|(past[maxb][1]<<maxb); 55 dp[maxb][0] = dp[maxb+1][1]|(past[maxb][0]<<maxb); 56 for( int i=maxb-1; i>=0; i-- ) { 57 for( int j=0; j<=1; j++ ) 58 dp[i][0] = max( dp[i][0], dp[i+1][0]|(past[i][j]<<i) ); 59 for( int j=0; j<top[i]; j++ ) 60 dp[i][0] = max( dp[i][0], dp[i+1][1]|(past[i][j]<<i) ); 61 dp[i][1] = dp[i+1][1]|(past[i][top[i]]<<i); 62 } 63 printf( "%u\n", max(dp[0][0],dp[0][1]) ); 64 } 65 }