[AGC034F] RNG y XOR

título

  Haga clic aquí para ver el tema.

análisis

  La primera etapa puede ser \ (A \) matriz se convierte en una probabilidad \ (P (J) \) : cada paso o iso \ (J \) de probabilidad.
  Posteriormente encontrado, \ (X \) de \ (0 \) se convierte en \ (I \) es igual a una deseada \ (X \) de \ (I \) se convierte en \ (0 \) deseado.
  Así que nuestro punto de partida, aunque no es la misma, pero el punto final es el mismo. De esta manera podemos aplicar el modelo de paseo aleatorio:
  \ (f (i) \) : De \ (i \) se convierte en el punto de partida \ \ (0) expectativas.
  Las condiciones de contorno \ (f (0) = 0 \) , el resto de la transferencia de la siguiente forma:

\ [\ Begin {alineado} & f (i) = 1 + \ sum_ {j = 0} ^ {2 ^ n-1} P (j) f (i \ oplus j) \\ \ Rightarrow & f (i) = 1 + \ sum_ {j \ oplus k = i} P (j) f (k) \\ \ Rightarrow & f (i) -1 = \ sum_ {j \ oplus k = i} P (j) f (k) \ end {alineado } \]

  Encontramos que \ (f \) es un semejante "rodar su propio propia" transferencia. Pero todavía no es el mismo, porque más constante -1.
  Nos ponemos en forma de convolución:

\ [(F (0), f (1), f (2), ..., f (2 ^ n-1)) \ bigoplus (P (0), P (1), P (2) ,. .., P (2 ^ n-1)) = (f ?, (1) -1, f (2) -1, ..., f (2 ^ n-1) -1) \]

  Encontramos un enrollado no se puede determinar cuánto del 0, porque nuestra frontera es la transferencia de \ (f (0) = 0 \) .
  Pero que rollo a cabo el primer set a 0 \ (los ejes X \) , se puede obtener:

\ [\ Begin {alineado} x + \ sum_ {i = 1} ^ {2 ^ n-1} (f (i) -1) y = \ sum_ {i = 0} ^ {2 ^ n-1} \ sum_ {j \ oplus k = i} P (j) f (k) \\ & = \ sum_ {i = 0} ^ {2 ^ n-1} f (i) \ sum_ {j = 0} ^ {2 ^ n-1} P (j) \\ & = \ sum_ {i = 0} ^ {2 ^ n-1} f (i) \ end {alineado} \]

  En otras palabras, debemos despliegue de algo original \ (f \) y es el mismo.
  Puede entonces ser obtenido \ (X = F (0) + ^ n-2 1- \.) :

\ [(F (0), f (1), f (2), ..., f (2 ^ n-1)) \ bigoplus (P (0), P (1), P (2) ,. .., P (2 ^ n-1)) = (f (0) + 2 ^ n-1, f (1) -1, f (2) -1, ..., f (2 ^ n-1 ) -1) \]

  Encontramos que \ (f \) Resultados del vector y el vector de comparación gusta, y hay parte pública, podemos considerar la soda:

\ [(F (0), f (1), f (2), ..., f (2 ^ n-1)) \ bigoplus (P (0) -1, P (1), P (2) , ..., P (2 ^ n-1)) = (2 ^ n-1, -1, -1, ..., - 1) \]

  Después de esto podemos utilizar para obtener la transformada FWT \ (f \) del vector.
  Pero vamos a ser el primer caso de 0 es 0 después del descubrimiento del FWT, no en este momento yuanes de inversión.
  Sin embargo, mientras que \ (f (0) \) valores después de la conversión \ (f '(0) \ ) es sin restricciones. Por lo tanto, podemos dar \ (f '(0) \ ) en un valor arbitrario, como \ (0 \) . 0 después de la primera transformación inversa es \ (k \) . \ (F \) en cada uno de ustedes va a contribuir más \ (k \) , al igual que perder.

código

#include <cstdio>

const int mod = 998244353, inv2 = 499122177;
const int MAXN = 20, MAXL = ( 1 << 18 ) + 5;

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' );
}

int F[MAXL], p[MAXL], h[MAXL];
int N, len;

int qkpow( int base, int indx )
{
	int ret = 1;
	while( indx )
	{
		if( indx & 1 ) ret = 1ll * ret * base % mod;
		base = 1ll * base * base % mod, indx >>= 1;
	}
	return ret;
}

int inv( const int a ) { return qkpow( a, mod - 2 ); }
int fix( const int x ) { return ( x % mod + mod ) % mod; }

void FWT( int *f, const int mode )
{
	int t1, t2;
	for( int s = 2 ; s <= len ; s <<= 1 )
		for( int i = 0, t = s >> 1 ; i < len ; i += s )
			for( int j = i ; j < i + t ; j ++ )
			{
				t1 = f[j], t2 = f[j + t];
				if( mode > 0 ) f[j] = ( t1 + t2 ) % mod, f[j + t] = fix( t1 - t2 );
				else f[j] = 1ll * ( t1 + t2 ) * inv2 % mod, f[j + t] = 1ll * fix( t1 - t2 ) * inv2 % mod;
			}
}

int main()
{
	int s = 0;
	read( N ); len = 1 << N;
	for( int i = 0 ; i < len ; i ++ ) read( p[i] ), s = ( s + p[i] ) % mod;
	s = inv( s );
	for( int i = 0 ; i < len ; i ++ ) p[i] = 1ll * p[i] * s % mod;
	for( int i = 1 ; i < len ; i ++ ) h[i] = mod - 1;
	h[0] = len - 1, p[0] = fix( p[0] - 1 );
	FWT( h, 1 ), FWT( p, 1 );
	for( int i = 1 ; i < len ; i ++ ) F[i] = 1ll * h[i] * inv( p[i] ) % mod;
	FWT( F, -1 );
	int tmp = mod - F[0];
	for( int i = 0 ; i < len ; i ++ ) write( ( tmp + F[i] ) % mod ), putchar( '\n' );
	return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/crashed/p/12592760.html
Recomendado
Clasificación