El número de cadenas binarias que deben tener 1 a la izquierda de 0
Descripción del Título
Dado un entero n, encuentre el número de cadenas con un carácter "1" en el lado izquierdo del carácter "0" entre todas las cadenas de longitud n que constan de caracteres "0" y caracteres "1".
Ingrese una descripción:
Ingrese una línea que contenga un número entero n (1 ≤ n ≤ 2 ∗ 1 0 7) n (1 \ leq n \ leq2 * 10 ^ 7)n ( 1≤norte≤2∗1 07 )。
Descripción de salida:
Genere un número entero para indicar la respuesta devuelta. Debido a la gran cantidad de cadenas, es posible que se desborde. Genere 2 29 2 ^ {29}22 La respuesta después de 9 módulo.
Ejemplo 1
entrar
1
Salida
1
Descripción
只有“1”满足
Ejemplo 2
entrar
2
Salida
2
Descripción
只有“10”和“11”满足
Ejemplo 3
entrar
3
Salida
3
Descripción
只有“101”,“110”,“111”满足
responder:
Cuando dibujamos en papel, podemos encontrar que los primeros elementos son: 1 2 3 5 8 13…, la secuencia obvia de Fibonacci. El rango de datos es un poco grande, O (n) O (n)O ( n ) no debería pasar, use la exponenciación rápida de matriz y listo.
Código:
#include <cstdio>
#include <cstring>
using namespace std;
const long MOD = 1 << 29;
int n;
long c[2][2];
void matmul(long a[][2], long b[][2]) {
memset(c, 0, sizeof c);
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 2; ++j) {
for (int k = 0; k < 2; ++k) {
c[i][j] += a[i][k] * b[k][j] % MOD;
c[i][j] %= MOD;
}
}
}
memcpy(a, c, sizeof c);
}
int solve(int m) {
long ans[][2] = {
{
1,1}, {
1,0} };
long ret[][2] = {
{
1,0}, {
0,1} };
while (m) {
if (m & 1) matmul(ret, ans);
matmul(ans, ans);
m >>= 1;
}
return ret[0][0];
}
int main(void) {
scanf("%d", &n);
if (n < 3) return 0 * printf("%d\n", n);
printf("%d\n", solve(n));
return 0;
}