Конкатенація двох паліндромів#9592

Конкатенація двох паліндромів (Розбір)

Уявімо рядок довжини у вигляді конкатенації двох непустих паліндромів довжин та n - l.

Розглянемо паліндром довжини . Оскільки паліндром читається однаково зліва направо і справа наліво, його друга половина повністю визначається першою. Тому достатньо довільно вибрати лише перші (l + 1) / 2 символів: кожен з них може бути будь-якою з букв алфавіту. Решту символів однозначно відновлюють так, щоб рядок був паліндромом.

Таким чином, загальна кількість паліндромів довжини дорівнює k^{(l+1)/2}.

Аналогічно, для паліндрома довжини n - l його друга половина повністю визначається першою. Тому перші (n - l + 1) / 2 символів можна обрати довільним чином, обираючи кожен з них з букв алфавіту, а інші символи однозначно визначаються умовою паліндрому.

Відповідно, кількість паліндромів довжини n - l дорівнює k^{(n-l+1)/2}.

Побудувати конкатенацію двох паліндромів з довжинами та n - l можна

k^{(l+1)/2} \cdot k^{(n-l+1)/2}

способами. Оскільки жоден з паліндромів не повинен бути пустим, то 1 \le l \le n - 1. Загальна кількість можливих паліндромів дорівнює

\sum_{l=1}^{n-1} k^{(l+1) \over 2} \cdot k^{(n-l+1) \over 2}

Всі операції слід проводити за модулем 10^9 + 7.

Приклад

Розглянемо другий приклад, у якому довжина рядка дорівнює , а алфавіт складається з двох букв. Нехай це будуть букви та .

Таким чином, існує рівно шуканих рядків довжини :

Реалізація алгоритму

Виконання розрахунків проводиться за модулем 10^9 + 7. Визначимо модуль .

#define MOD 1000000007

Функція powmod обчислює значення x^n~mod~m.

long long powmod(long long x, long long n, long long m)
{
  if (n == 0) return 1;
  if (n % 2 == 0) return powmod((x * x) % m, n / 2, m);
  return (x * powmod(x, n - 1, m)) % m;
}

Основна частина програми. Читаємо вхідні дані.

scanf("%d %d", &n, &k);

Обчислюємо відповідь за формулою.

res = 0;
for (l = 1; l < n; l++)
  res = (res + powmod(k, (l + 1) / 2, MOD) * 
               powmod(k, (n - l + 1) / 2, MOD)) % MOD;

Виводимо відповідь.

printf("%lld\n", res);

Java реалізація

import java.util.*;
 
public class Main
{
  public final static long MOD = 1000000007;
  
  static long PowMod(long x, long n, long m)
  {
    if (n == 0) return 1;
    if (n % 2 == 0) return PowMod((x * x) % m, n / 2, m);
    return (x * PowMod(x, n - 1, m)) % m;
  }

  public static void main(String[] args)
  {
    Scanner con = new Scanner(System.in);
    long n = con.nextLong();
    long k = con.nextLong();    
    long res = 0;
    for (long l = 1; l < n; l++)
      res = (res + PowMod(k, (l + 1) / 2, MOD) * 
                   PowMod(k, (n - l + 1) / 2, MOD)) % MOD;
    System.out.println(res);
    con.close();
  }
}

Python реалізація

Розрахунки проводяться за модулем 10^9 + 7. Визначимо модуль .

mod = 10 ** 9 + 7

Читаємо вхідні дані.

n, k = map(int, input().split())

Обчислюємо відповідь за формулою.

res = 0;
for l in range(1,n):
  res = (res + pow(k, (l + 1) // 2, mod) * 
               pow(k, (n - l + 1) // 2, mod)) % mod;

Виводимо відповідь.

print(res)