zoukankan      html  css  js  c++  java
  • Solution -「NOI 2021」「洛谷 P7740」机器人游戏

    (mathcal{Description})

      Link.

      自己去读题面叭~

    (mathcal{Solution})

      首先,参悟【样例解释 #2】。一种暴力的思路即为钦定集合 (S) 内的位置都合法,容斥计数。其中对于每条纸带的每个位置,有三种情况(令 _ 为“保持不变”,注意没有被机器人经过的位置都有这种修改):

    • 同时存在 _*;或者同时存在 01:只能为空,方案数为 (1)
    • 否则,存在(_*)且存在(01):只能为空或 01 中的一个,方案数为 (2)
    • 否则,方案数为 (3)

      暴力做的复杂度是 (mathcal O(2^nn^am^b))(a,b) 看细节实现,不太可观。

      尝试钦定最后一个在 (S) 中的位置为 (r),那么所有修改长度大于 (n-r+1) 的机器人所在的纸带都必须全空。在此限制下带着容斥系数状压 DP,令 (f(i,S)) 表示考虑了纸带的位置 (i),前若干个位置的选择情况为 (S),注意此处 (|S|le2^{min{i,n-r}}=mathcal O(2^{n/2})),转移时可以 (mathcal O(nm)) 暴力计算当前位置的贡献,得到了 (mathcal O(2^{n/2}nm)) 的算法。

      顺带,注意到统计当前位置贡献时可以描述为形如“有多少个机器人的修改序列中,下标属于 (S) 的位置上存在 _/*/0/1”,可以用 std::bitset 优化。最终复杂度为 (mathcal O(frac{2^{n/2}nm}{omega}))

    (mathcal{Code})

    /*~Rainybunny~*/
    
    #include <bitset>
    #include <cstdio>
    #include <cassert>
    #include <cstring>
    
    #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
    #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
    
    typedef unsigned long long ULL;
    
    const int MAXN = 32, MAXM = 1e3, MOD = 1e9 + 7;
    int n, m, pw2[MAXM + 5], pw3[MAXM + 5];
    
    inline int imin( const int a, const int b ) { return a < b ? a : b; }
    inline void subeq( int& a, const int b ) { ( a -= b ) < 0 && ( a += MOD ); }
    inline int mul( const int a, const int b ) { return int( 1ll * a * b % MOD ); }
    inline int add( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
    inline void addeq( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD ); }
    
    struct Robot {
    	int len, val[MAXN + 5];
    	inline int operator [] ( const int k ) const {
    		return k <= len ? val[k] : 0;
    	}
    	inline void read() {
    		static char str[105]; scanf( "%s", str );
    		val[len = 1] = 0;
    		for ( int i = 0; str[i]; ++i ) {
    			if ( str[i] == 'R' ) val[++len] = 0;
    			else if ( str[i] == '0' ) val[len] = 1;
    			else if ( str[i] == '1' ) val[len] = 2;
    			else val[len] = 3 - val[len];
    		}
    	}
    } rbt[MAXM + 5];
    
    inline int solve( const int r ) {
    	static int f[2][1 << 17][2];
    	static std::bitset<MAXM + 5> sig[MAXN + 5][4], g[1 << 17][4];
    	int allc = 0;
    	
    	rep ( i, 0, n - 1 ) rep ( j, 0, 3 ) sig[i][j].reset();
    	rep ( i, 1, m ) if ( rbt[i].len <= n - r + 1 ) {
    		++allc;
    		rep ( j, 0, n - 1 )
    			sig[j][rbt[i][j + 1]].set( i );
    	}
    	rep ( i, 0, imin( n - r, r ) ) rep ( j, 0, 3 ) {
    		g[1 << i][j] = sig[i][j];
    	}
    	
    	rep ( S, 1, ( 1 << imin( n - r, r ) << 1 ) - 1 ) if ( S & ( S - 1 ) ) {
    		rep ( i, 0, 3 ) {
    			g[S][i] = g[S ^ ( S & -S )][i] | g[S & -S][i];
    		}
    	}
    	
    	auto calc = [&]( const bool sty, const ULL S )->int {
    		static std::bitset<MAXM + 5> x, y;
    		x = ( sty ? g[S][3] : g[S][0] & g[S][3] ) | ( g[S][1] & g[S][2] );
    		y = ~x & ( sty ? g[S][1] | g[S][2] :
    		  ( g[S][0] | g[S][3] ) & ( g[S][1] | g[S][2] ) );
    		int t = y.count();
    		return mul( pw2[t], pw3[allc - t - x.count()] );
    	};
    	
    	memset( f[0], 0, sizeof f[0] ), f[0][0][0] = 1;
    	for ( int i = 0, sta = 0; i < r; ++i, sta ^= 1 ) {
    		memset( f[!sta], 0, sizeof f[!sta] );
    	  	rep ( S, 0, ( 1 << imin( i, n - r ) ) - 1 ) {
    			ULL T = ULL( S ) << 1ull & ( ( 1ull << n >> r ) - 1 );
    			bool flg = ULL( S ) << 1ull << r >> n & 1ull;
    			
    			rep ( t, 0, 1 ) {
    				int cur = f[sta][S][t]; f[sta][S][t] = 0;
    				if ( !cur ) continue;
    				subeq( f[!sta][r == n ? 0 : T | 1][t || flg || r == n],
    				  mul( cur, calc( t || i + 1 < r, S << 1 | 1 ) ) );
    				if ( i + 1 < r ) {
    					addeq( f[!sta][T][t || flg],
    					  mul( cur, calc( 1, S << 1 ) ) );
    				}
    			}
    		}
    	}
    
    	int ret = 0;
    	rep ( t, 0, 1 ) {
    		for ( int d = 1, sta = r & 1; d <= n - r; ++d, sta ^= 1 ) {
    			rep ( i, 0, imin( r, n - r ) - 1 ) {
    				rep ( j, t, 3 ) g[1 << i][j] = sig[i + d][j];
    			}
    			rep ( S, 0, ( 1 << imin( r, n - r ) ) - 1 ) {
    				if ( S & ( S - 1 ) ) {
    					rep ( j, t, 3 ) {
    						g[S][j] = g[S ^ ( S & -S )][j] | g[S & -S][j];
    					}
    				}
    				f[!sta][S][t] = mul( f[sta][S][t], calc( t, S ) );
    				f[sta][S][t] = 0;
    			}
    		}
    		rep ( S, 0, ( 1 << imin( r, n - r ) ) - 1 ) {
    			addeq( ret, f[n & 1][S][t] );
    		}
    	}
    	return ret;
    }
    
    int main() {
        // freopen( "robot.in", "r", stdin );
        // freopen( "robot.out", "w", stdout );
        
    	scanf( "%d %d", &n, &m );
    	pw2[0] = pw3[0] = 1;
    	rep ( i, 1, m ) {
    		rbt[i].read();
    		pw2[i] = mul( 2, pw2[i - 1] ), pw3[i] = mul( 3, pw3[i - 1] );
    	}
    	
    	int ans = 0;
    	rep ( i, 1, n ) subeq( ans, solve( i ) );
    	printf( "%d
    ", ans );
    	return 0;
    }
    
    
  • 相关阅读:
    机器学习之--数据构造,函数图显示
    python 用xlwt包把数据导出到excel表中
    python实现Hbase
    Hbase命令
    scrapy Formrequest用法(豆瓣登录案例)
    scrapy meta不用pipe用命令-o
    scrapy之Crawspider 腾讯招聘实战案例
    scrapy选择器归纳
    scrapy response.xpath可以提取包含字符XX的标签
    初涉.....编码__列表__字典
  • 原文地址:https://www.cnblogs.com/rainybunny/p/15115936.html
Copyright © 2011-2022 走看看