Advertisement
dmkozyrev

matrix

Jan 22nd, 2016
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.24 KB | None | 0 0
  1. #include <stdio.h>
  2.  
  3. // Работа с числами в кольце по модулю n:
  4. void mod(int * val, int n); // Функция вычисляет значение val по модулю n
  5. void inc(int * val, int n, int k); // Функция увеличивает значение val на k по модулю n
  6. void dec(int * val, int n, int k); // Функция уменьшает значение val на k по модулю n
  7.  
  8. // Работа с матрицами:
  9. void copy(int * A, int * B); // Копирует двумерную матрицу B в матрицу A
  10. void print(int * A); // Выводит двумерную матрицу на экран
  11. void prod(int * A, int * B, int * C, int n); // В матрицу C записывается результат умножения матрицы A на матрицу B по модулю n
  12. void power(int * A, int k, int n); // Возводит матрицу A в степень k. Элементы матрицы вычисляются по модулю n
  13.  
  14. int main(){
  15. //  Ввод начальных условий:
  16.     int a, b, x1, x2, n, base;
  17.     printf("X(n) = a*X(n-1)+b*X(n-2), X(n) (mod base)\n");
  18.     printf("Enter a, b, X(1), X(2), n, base: ");
  19.     scanf("%d %d %d %d %d %d", &a, &b, &x1, &x2, &n, &base);
  20.    
  21. //  Получение матрицы оператора:
  22.     unsigned const int SIZE = 2; // Размерность матрицы
  23.     int A[SIZE][SIZE]; // Матрица оператора
  24.     A[0][0] = 0; A[0][1] = b;
  25.     A[1][0] = 1; A[1][1] = a;
  26.    
  27. //  Возведение матрицы оператора в степень:
  28.     int * ptr_A = (int*) A; // Указатель на матрицу оператора
  29.     power(ptr_A, n-1, base);
  30.    
  31. //  Вычисление n-го члена последовательности:
  32.     int xn = A[0][0]*x1 + A[1][0]*x2;
  33.     mod(&xn, base); // Взятие его по модулю
  34.    
  35. //  Вывод ответа на экран:
  36.     printf("X(%d) = %d\n", n, xn);
  37.        
  38.     return 0;
  39. }
  40.  
  41. void mod(int * val, int n){
  42. //  Функция вычисляет значение val по модулю n 
  43.     *val = (*val >= 0) ? (*val % n) : (n-(-*val) % n);
  44. }
  45.  
  46. void inc(int * val, int n, int k){
  47. //  Функция увеличивает значение val на k по модулю n
  48.     mod(&k, n);
  49.     *val += k;
  50.     mod(val, n);
  51. }
  52.  
  53. void dec(int * val, int n, int k){
  54. //  Функция уменьшает значение val на k по модулю n
  55.     mod(&k, n);
  56.     *val -= k;
  57.     mod(val, n);
  58. }
  59.  
  60. void prod(int * A, int * B, int * C, int n){
  61. //  В матрицу C записывается результат умножения матрицы A на матрицу B.
  62. //  Работа ведется в кольце вычетов по модулю n
  63.    
  64.     int i, j, k, size = 2; // i, j, k - счетчики, size - размерность матриц
  65.    
  66. //  Напоминание: в указательной арифметике C[i][j] записывается как *(C+size*i+j)
  67. //  При работе с многомерными массивами внутри функции в Си доступна только указательная арифметика
  68.  
  69. //  Обнуляем все элементы матрицы C:
  70.     for (i = 0; i < size; i++)
  71.         for (j = 0; j < size; j++)
  72.             *(C+i*size+j) = 0;
  73.    
  74. //  В C[i][j] Записываем результат произведения i-ой строки матрицы A на j-ый столбец матрицы B:
  75.     for (i = 0; i < size; i++)
  76.         for (j = 0; j < size; j++)
  77.             for (k = 0; k < size; k++){
  78.                 int d = *(A+i*size+k) * *(B+k*size+j); // Произведение A[i][k] на B[k][j]
  79.                 inc(C+i*size+j, n, d); // Добавляем к C[i][j] значение d
  80.             }
  81. }
  82.  
  83. void copy(int * A, int * B){
  84. //  Копирует двумерную матрицу B в матрицу A
  85.     int i, j, size = 2;
  86.     for(i=0; i < size; i++)
  87.         for(j=0; j< size; j++)
  88.             *(A+size*i+j) = *(B+size*i+j);
  89. }
  90.  
  91. void print(int * A){
  92. //  Выводит двумерную матрицу на экран:
  93.     int i, j, SIZE = 2;
  94.     for (i = 0; i < SIZE; i++, printf("\n"))
  95.         for (j = 0; j < SIZE; j++)
  96.             printf("%d ", *(A+SIZE*i+j));
  97. }
  98.  
  99. void power(int * A, int k, int n){
  100. //  Быстрым возведением в степень возводит матрицу A в степень k. Значения элементов матрицы берутся по модулю n.
  101.     unsigned const int SIZE = 2;
  102.     int M[SIZE][SIZE]; // Матрица M, в которой будем хранить промежуточные вычисления
  103.     int T[SIZE][SIZE]; // В матрицу T будем записывать эти вычисления, а потом копировать в переменную M
  104.    
  105. //  Сделаем матрицу M единичной:
  106.     M[0][0] = 1; M[0][1] = 0;
  107.     M[1][0] = 0; M[1][1] = 1;
  108.    
  109.     int *ptr_M = (int*)M; // Указатель на матрицу M
  110.     int *ptr_T = (int*)T; // Указатель на матрицу T
  111.        
  112.     while (k > 0){
  113.         if (k % 2 != 0){
  114.             prod(ptr_M, A, ptr_T, n); // T = M * A;
  115.             k--;
  116.         } else {
  117.             prod(ptr_M, ptr_M, ptr_T, n); // T = M^2
  118.             k /= 2;
  119.         }  
  120.         copy(ptr_M, ptr_T); // M = T
  121.     }
  122.    
  123.     copy(A, ptr_M); // Копирование ответа в переменную A
  124. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement