• [NOI Online #3]魔法值


    题目

      点这里看题目。

    分析

      我们不难想到,对于系数进行一下的拆分:

    [egin{aligned} f(u,j)&=igoplus_{(u,v)in E} f(v,j-1)\ &=igoplus_{(u,v)in E}igoplus_{(v,w)in E} f(w,j-2)\ &...\ &=igoplus_{xin V} f(x,0) imes C^j_{u,x} end{aligned} ]

      其中,(C^j_{u,x})表示恰好走(j)步时,从(u)(x)的方案数
      根据异或的性质,我们实际上只会关心(C^j_{u,x})的奇偶性。
      怎么求这个东西呢?我们可以想到用矩阵乘法。
      初始矩阵就是邻接矩阵:

    [T_{i,j}= egin{cases} 1 & (i,j)in E\ 0 & (i,j) ot in E end{cases} ]

      现在对于一个询问(a_i),我们发现我们需要的系数实际上就是(T^{a_i}),这个东西可以用矩阵快速幂快速地求出来。
      单纯地按照上面的方法,时间是(O(n^3sumlog_2a)),不妙。
      再仔细想一想,我们明明只需要从 1 出发的信息(只需要(C^{a_i}_1)),使用矩阵快速幂却多算了很多。
      考虑(C^{a_i}_1)实际上是:

    [ oldsymbol v = {1,0,0,...}\ C^{a_i}_1=v imes T^{a_i} ]

      一个向量与矩阵相乘,时间是(O(n^2))的。因此,我们可以将求出(C^{a_i})的时间缩减到(O(n^2)),总时间(O(n^2sum log_2a)),可过。
      实际操作中,我们需要预处理出(T)的倍增,避免每次重新计算,导致复杂度退化。

    代码

    #include <cstdio>
    #include <cstring>
    
    typedef long long LL;
    
    const int MAXN = 105, MAXLOG = 40;
    
    template<typename _T>
    void read( _T &x )
    {
    	x = 0;char s = getchar();int f = 1;
    	while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
    	while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
    	x *= f;
    }
    
    template<typename _T>
    void write( _T x )
    {
    	if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
    	if( 9 < x ){ write( x / 10 ); }
    	putchar( x % 10 + '0' );
    }
    
    struct matrix
    {
    	bool mat[MAXN][MAXN];
    	int n, m;
    	matrix() { n = m = 0, memset( mat, false, sizeof mat ); }
    	matrix( const int N, const int M ) { n = N, m = M, memset( mat, false, sizeof mat ); }
    	bool* operator [] ( const int indx ) { return mat[indx]; }
    	
    	matrix operator * ( matrix b ) const
    	{
    		matrix ret = matrix( n, b.m );
    		for( int i = 1 ; i <= ret.n ; i ++ )
    			for( int k = 1 ; k <= m ; k ++ )
    				if( mat[i][k] )
    					for( int j = 1 ; j <= ret.m ; j ++ )
    						ret[i][j] ^= mat[i][k] & b[k][j];
    		return ret;
    	}
    	
    	void operator *= ( matrix b ) { *this = *this * b; }
    };
    
    matrix B[MAXLOG], A;
    LL f[MAXN];
    int N, M, Q;
    
    int main()
    {
    	read( N ), read( M ), read( Q );
    	B[0] = matrix( N, N );
    	for( int i = 1 ; i <= N ; i ++ ) read( f[i] );
    	for( int i = 1, a, b ; i <= M ; i ++ )
    		read( a ), read( b ), B[0][a][b] = B[0][b][a] = 1;
    	for( int i = 1 ; i <= 32 ; i ++ ) B[i] = B[i - 1] * B[i - 1];
    	while( Q -- )
    	{
    		LL a; read( a );
    		A = matrix( 1, N ), A[1][1] = 1;
    		for( int i = 32 ; ~ i ; i -- )
    			if( a >> i & 1 )
    				A *= B[i];
    		LL ans = 0;
    		for( int i = 1 ; i <= N ; i ++ ) 
    			if( A[1][i] )
    				ans ^= f[i];
    		write( ans ), putchar( '
    ' );
    	}
    	return 0;
    }
    
  • 相关阅读:
    升级系统引起的
    php curl批处理
    看《黑炮事件》想到的
    查找单链表的倒数第k个值
    python绘制树枝
    暑假第九测
    网络流24题(持续更新)
    P2657 [SCOI2009]windy数
    P3177 [HAOI2015]树上染色
    暑假第六测
  • 原文地址:https://www.cnblogs.com/crashed/p/12990955.html
Copyright © 2020-2023  润新知