「UVA12183」Top Secret

题目

点这里看题目。

分析

可以发现题目提到的 decryption 其实就是一个线性变换:

[M= egin{bmatrix} 1&R&0&dots&0&L\ L&1&R&dots&0&0\ 0&L&1&dots&0&0\ vdots&vdots&vdots&ddots&vdots&vdots\ 0&0&0&dots&1&R\ R&0&0&dots&L&1 end{bmatrix} ]

如果直接算矩阵乘法,复杂度是 (O(n^3log S)) 的,无法接受。

注意到 (M) 是一个循环矩阵,这意味着我们可以将它拆解为多项式的形式:

[egin{aligned} M&=E^0+RE^1+LE^{n-1}\ E&= egin{bmatrix} 0&1&0&dots&0&0\ 0&0&1&dots&0&0\ 0&0&0&dots&0&0\ vdots&vdots&vdots&ddots&vdots&vdots\ 0&0&0&dots&0&1\ 1&0&0&dots&0&0 end{bmatrix} end{aligned} ]

对于多项式做循环卷积,接着我们就可以还原出 (M^S)。这样复杂度就是 (O(n^2log S)) 的。

小结:循环矩阵比较少见,一般可以将它和多项式结合起来看

代码

#include <cstdio>

#define rep( i, a, b ) for( int i = (a) ; i <= (b) ; i ++ )
#define per( i, a, b ) for( int i = (a) ; i >= (b) ; i -- )

const int MAXN = 1005;

template<typename _T>
void read( _T &x )
{
	x = 0; char s = getchar(); bool f = false;
	while( s < '0' || '9' < s ) { f = ( s == '-' ), s = getchar(); }
	while( '0' <= s && s <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar(); }
	if( f ) x = -x;
}

template<typename _T>
void write( _T x )
{
	if( x < 0 ) putchar( '-' ), x = -x;
	if( 9 < x ) write( x / 10 );
	putchar( x % 10 + '0' );
}

int mat[MAXN][MAXN];
int F[MAXN], G[MAXN], tmp[MAXN];

int A[MAXN];
int N, S, L, R, X, mod;

inline int Mul( int x, int v ) { return 1ll * x * v % mod; }
inline int Sub( int x, int v ) { return ( x -= v ) < 0 ? x + mod : x; }
inline int Add( int x, int v ) { return ( x += v ) >= mod ? x - mod : x; }

void Convolute( int *ret, const int *P, const int *Q )
{
	rep( i, 0, N - 1 ) tmp[i] = 0;
	rep( i, 0, N - 1 ) rep( j, 0, N - 1 )
		tmp[( i + j ) % N] = Add( tmp[( i + j ) % N], Mul( P[i], Q[j] ) );
	rep( i, 0, N - 1 ) ret[i] = tmp[i];
}

int main()
{
	int T;
	read( T );
	while( T -- )
	{
		read( N ), read( S ), read( L ), read( R ), read( X );
		rep( i, 0, N - 1 ) read( A[i] );
		mod = 1; rep( i, 1, X ) mod *= 10;
		rep( i, 0, N - 1 ) G[i] = F[i] = 0;
		G[0] = 1 % mod;
		F[0] = 1 % mod, F[1] = R % mod, F[N - 1] = L % mod;
		while( S )
		{
			if( S & 1 ) Convolute( G, G, F );
			Convolute( F, F, F ), S >>= 1;
		}
		for( int i = 0 ; i < N ; i ++ )
			for( int k = 0 ; k < N ; k ++ )
				mat[k][( i + k ) % N] = G[i];
		rep( i, 0, N - 1 )
		{
			int ans = 0;
			rep( j, 0, N - 1 ) ans = Add( ans, Mul( mat[i][j], A[j] ) );
			write( ans ), putchar( i == N - 1 ? '
' : ' ' );
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/crashed/p/15339091.html