题目
点这里看题目。
分析
我们不难想到,对于系数进行一下的拆分:
[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;
}