İki palindromun konkatenasiyası#9592

İki palindromun konkatenasiyası (Həll təhlili)

Strinqi uzunluğu olan iki boş olmayan palindrome uzunluqları və n - l olaraq təmsil edək.

Uzunluğu olan palindrome nəzərdən keçirək. Çünki palindrome həm sağdan sola, həm də soldan sağa eyni şəkildə oxunur, onun ikinci yarısı tamamilə birinci yarı ilə müəyyən edilir. Buna görə yalnız ilk (l + 1) / 2 simvollarını sərbəst seçmək kifayətdir: onların hər biri hərfi olan əlifbadan hər hansı biri ola bilər. Qalan simvollar palindrome olmaq şərti ilə dəqiq olaraq bərpa edilir.

Beləliklə, uzunluğu olan palindrome-ların ümumi sayı k^{(l+1)/2}-ə bərabərdir.

Bənzər şəkildə, uzunluğu n - l olan palindrome üçün ikinci yarısı tamamilə birinci yarı ilə müəyyən edilir. Buna görə ilk (n - l + 1) / 2 simvolları sərbəst şəkildə seçilə bilər, kitab hərfi olan əlifbadan hər hansı biri ola bilər və qalan simvollar palindrome olmaq şərti ilə dəqiq müəyyən edilir.

Nəticədə, uzunluğu n - l olan palindrome-ların sayı k^{(n-l+1)/2}-ə bərabərdir.

Uzunluqları və n - l olan iki palindrome-u birləşdirmək

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

şəkillərdə mümkündür. Çünki heç bir palindrome boş olmamalıdır, onda 1 \le l \le n - 1. Mümkün palindrome-ların ümumi sayı belədir

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

Bütün əməliyyatlar 10^9 + 7 moduluna görə həyata keçirilməlidir.

Misal

Simvollardan ibarət olan ikinci misalı nəzərdən keçirək, burada hərflərdən ibarət seriya uzunluğundadır və əlifba iki hərfdən ibarətdir. Bunlar və hərfləri olsun.

Beləliklə, tam olaraq axtarılan simvol uzunluğu var:

Alqoritmin reallaşdırılması

Hesablama 10^9 + 7 moduluna görə aparılır. Modulu olaraq təyin edək.

#define MOD 1000000007

powmod funksiyası x^n~mod~m dəyərini hesablayır.

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

Əsas proqramın hissəsi. Giriş məlumatlarını oxuyuruq.

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

Formulaya görə cavabı hesablayırıq.

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

Cavabı çıxardırıq.

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

Java reallaşdırması

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 reallaşdırması

Hesablama 10^9 + 7 moduluna görə aparılır. Modulu olaraq təyin edək.

mod = 10 ** 9 + 7

Giriş məlumatlarını oxuyuruq.

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

Formulaya görə cavabı hesablayırıq.

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

Cavabı çıxardırıq.

print(res)