Guest User

dalex

a guest
Jul 1st, 2011
646
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 4.62 KB | None | 0 0
  1. const
  2.     size: longint = 8;
  3.     md: int64 = 1000 * 1000 * 1000 + 7;
  4.  
  5. type
  6.     vector = record
  7.         vect: array[1..20] of int64;
  8.     end;
  9.     matrix = record
  10.         matr: array[1..20, 1..20] of int64;
  11.     end;
  12.  
  13. var
  14.     l, r, ans: int64;
  15.     a: matrix;
  16.     x: vector;
  17.  
  18. function create_vector: vector;
  19. var i: longint; v: vector;
  20. begin
  21.     for i := 1 to size do
  22.     v.vect[i] := 0;
  23.     create_vector := v;
  24. end;
  25.  
  26. function create_matrix: matrix;
  27. var i, j: longint; z: matrix;
  28. begin
  29.     for i := 1 to size do
  30.         for j := 1 to size do
  31.             z.matr[i, j] := 0;
  32.     create_matrix := z;
  33. end;
  34.  
  35. function create_eye_matrix: matrix;
  36. var i, j: longint; e: matrix;
  37. begin
  38.     for i := 1 to size do
  39.         for j := 1 to size do
  40.             if i = j then
  41.                 e.matr[i, j] := 1
  42.             else
  43.                 e.matr[i, j] := 0;
  44.     create_eye_matrix := e;
  45. end;
  46.  
  47. function matrix_matrix_product(a, b: matrix): matrix;
  48. var i, j, k: longint; c: matrix;
  49. begin
  50.     c := create_matrix;
  51.     for i := 1 to size do
  52.         for j := 1 to size do
  53.             for k := 1 to size do
  54.                 c.matr[i, j] := (c.matr[i, j] + a.matr[i, k] * b.matr[k, j]) mod md;
  55.     matrix_matrix_product := c;
  56. end;
  57.  
  58. function matrix_sum(a, b: matrix): matrix;
  59. var i, j: longint; c: matrix;
  60. begin
  61.     c := create_matrix;
  62.     for i := 1 to size do
  63.         for j := 1 to size do
  64.             c.matr[i, j] := (a.matr[i, j] + b.matr[i, j]) mod md;
  65.     matrix_sum := c;
  66. end;
  67.  
  68. function matrix_vector_product(a: matrix; x: vector): vector;
  69. var i, j: longint; b: vector;
  70. begin
  71.     b := create_vector;
  72.     for i := 1 to size do
  73.         for j := 1 to size do
  74.             b.vect[i] := (b.vect[i] + a.matr[i, j] * x.vect[j]) mod md;
  75.     matrix_vector_product := b;
  76. end;
  77.  
  78. function matrix_pow(a: matrix; p: int64): matrix;
  79. var b: matrix;
  80. begin
  81.     if p = 0 then begin
  82.         matrix_pow := create_eye_matrix;
  83.         exit;
  84.     end;
  85.     if p mod 2 = 0 then begin
  86.         b := matrix_pow(a, p div 2);
  87.         matrix_pow := matrix_matrix_product(b, b);
  88.     end else
  89.         matrix_pow := matrix_matrix_product(a, matrix_pow(a, p - 1));
  90. end;
  91.  
  92. function sum_of_vector_components(v: vector): int64;
  93. var i: longint; s: int64;
  94. begin
  95.     s := 0;
  96.     for i := 1 to size do s := (s + v.vect[i]) mod md;
  97.     sum_of_vector_components := s;
  98. end;
  99.  
  100. function pow(a, p: int64): int64;
  101. var b: int64;
  102. begin
  103.     if p = 0 then begin
  104.         pow := 1;
  105.         exit;
  106.     end;
  107.     if p mod 2 = 0 then begin
  108.         b := pow(a, p div 2);
  109.         pow := (b * b) mod md;
  110.     end else
  111.         pow := (a * pow(a, p - 1)) mod md;
  112. end;
  113.  
  114. function inverse(a: int64): int64;
  115. begin
  116.     inverse := pow(a, md - 2);
  117. end;
  118.  
  119. function get_matrix_product(n: int64): matrix; // (E + A) * (E + A^2) * ... * (E + A^b)
  120. var i: longint; m: matrix;
  121. begin
  122.     m := create_eye_matrix;
  123.     i := 1;
  124.     while i <= n do begin
  125.         m := matrix_matrix_product(m, matrix_sum(create_eye_matrix, matrix_pow(a, i)));
  126.         i := i * 2;
  127.     end;
  128.     get_matrix_product := m;
  129. end;
  130.  
  131. function get_matrix_sum(n: int64): matrix; // E + A + A^2 + ... + A^n
  132. var a1, a2, m1, m2: matrix; b: int64;
  133. begin
  134.     if n = 0 then begin
  135.         get_matrix_sum := create_eye_matrix;
  136.         exit;
  137.     end;
  138.     if n = 1 then begin
  139.         get_matrix_sum := matrix_sum(create_eye_matrix, a);
  140.         exit;
  141.     end;
  142.     b := 1;
  143.     while 2 * b - 1 <= n do b := b * 2;
  144.     b := b div 2;
  145.     a1 := get_matrix_product(b);
  146.     a2 := create_matrix;
  147.     if n > 2 * b - 1 then begin
  148.         m1 := matrix_pow(a, 2 * b);
  149.         m2 := get_matrix_sum(n - 2 * b);
  150.         a2 := matrix_matrix_product(m1, m2);
  151.     end;
  152.     get_matrix_sum := matrix_sum(a1, a2);
  153. end;
  154.  
  155. function get_full(l, r: int64): int64;
  156. var m, m1, m2: matrix; v: vector;
  157. begin
  158.     m1 := matrix_pow(a, l - 2);
  159.     m2 := get_matrix_sum(r - l);
  160.     m := matrix_matrix_product(m1, m2);
  161.     v := matrix_vector_product(m, x);
  162.     get_full := (sum_of_vector_components(v) * inverse(2)) mod md;
  163. end;
  164.  
  165. function get_palind(l, r: int64): int64;
  166. begin
  167.     if l mod 2 = 0 then inc(l);
  168.     if r mod 2 = 0 then dec(r);
  169.     if l > r then
  170.         get_palind := 0
  171.     else begin
  172.         l := (l + 1) div 2;
  173.         r := (r + 1) div 2;
  174.         get_palind := get_full(l, r);
  175.     end;
  176. end;
  177.  
  178. function get_answer(l, r: int64): int64;
  179. var a, b: int64;
  180. begin
  181.     a := get_full(l, r);
  182.     b := get_palind(l, r);
  183.     get_answer := (a + b) mod md;
  184. end;
  185.  
  186. procedure init_dp;
  187. var i: longint;
  188. begin
  189.     x := create_vector;
  190.     for i := 1 to size do x.vect[i] := 1;
  191.     a := create_matrix;
  192.     a.matr[1, 3] := 1; a.matr[1, 7] := 1;
  193.     a.matr[2, 3] := 1; a.matr[2, 7] := 1;
  194.     a.matr[3, 1] := 1;
  195.     a.matr[4, 5] := 1;
  196.     a.matr[5, 4] := 1; a.matr[5, 8] := 1;
  197.     a.matr[6, 4] := 1; a.matr[6, 8] := 1;
  198.     a.matr[7, 2] := 1; a.matr[7, 6] := 1;
  199.     a.matr[8, 2] := 1; a.matr[8, 6] := 1;
  200. end;
  201.  
  202. begin
  203.     read(l, r);
  204.     ans := 0;
  205.     if (l = 1) and (r = 1) then begin
  206.         writeln(4);
  207.         halt;
  208.     end;
  209.     if (l = 1) then begin
  210.         ans := 4;
  211.         l := 2;
  212.     end;
  213.     init_dp;
  214.     ans := (ans + get_answer(l, r)) mod md;
  215.     writeln(ans);
  216. end.
Advertisement
Add Comment
Please, Sign In to add comment