3o_3v

fast fibonacci modulo numbers

Dec 19th, 2021
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 2.92 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. void mdot(long long **a, long long **b, long long**c, long long k, long long p) {
  5.     for(int i = 0; i < k; i++){
  6.         for(int j = 0; j < k; j++){
  7.             c[i][j] = 0;
  8.         }
  9.     }
  10.     for(int i = 0; i < k; i++){
  11.         for(int j = 0; j < k; j++){
  12.             for(int z = 0; z < k; z++){
  13.                 c[i][j] += (a[i][z]*b[z][j])%p;
  14.             }
  15.         }
  16.     }
  17. }
  18.  
  19. void mpow(long long **a, long n, long long k, long long p, long long** b) {
  20.     if(n == 0){
  21.         for(int i = 0; i < k; i++){
  22.             for(int j = 0; j < k; j++){
  23.                 if(i == j) b[i][j] = 1;
  24.                 else b[i][j] = 0;
  25.             }
  26.         }
  27.     }
  28.     if(n == 1){
  29.         for(int i = 0; i < k; i++){
  30.             for(int j = 0; j < k; j++){
  31.                 b[i][j] = a[i][j];
  32.             }
  33.         }
  34.     }else if(n%2 == 0){
  35.         long long** z = malloc(k*sizeof(long long*));
  36.         for(int i = 0; i < k; i++){
  37.             z[i] = malloc(k*sizeof(long long));
  38.         }
  39.         mpow(a, n/2, k, p, z);
  40.         mdot(z, z, b, k, p);
  41.         for(int i = 0; i < k; i++){
  42.             free(z[i]);
  43.         }
  44.         free(z);
  45.     }else{
  46.         long long** z = malloc(k*sizeof(long long*));
  47.         for(int i = 0; i < k; i++){
  48.             z[i] = malloc(k*sizeof(long long));
  49.         }
  50.         mpow(a, n-1, k, p, z);
  51.         mdot(z, a, b, k, p);
  52.         for(int i = 0; i < k; i++){
  53.             free(z[i]);
  54.         }
  55.         free(z);
  56.     }
  57. }
  58.  
  59. int main(void) {
  60.     long long k;
  61.     long long N;
  62.     long long p;
  63.     long long *F, **A;
  64.     scanf("%lld%lld%lld", &k, &N, &p);
  65.     F = malloc(k*sizeof(long long));
  66.     A = malloc(k*sizeof(long long *));
  67.     for (int i = 0; i < k; i++) {
  68.         scanf("%lld", &F[i]);
  69.         F[i] %= p;
  70.     }
  71.     for (int i = 0; i < k; i++) {
  72.         A[i] = malloc(k*sizeof(long long));
  73.         scanf("%lld", &A[0][i]);
  74.         A[0][i] %= p;
  75.     }
  76.  
  77.     if (N <= k) {
  78.         printf("%lld", F[N-1]);
  79.         free(F);
  80.         for(int i = 0; i < k; i++){
  81.             free(A[i]);
  82.         }
  83.         free(A);
  84.         return 0;
  85.     }
  86.     N -= k;
  87.  
  88.     for (int i = 1; i < k; i++) {
  89.         for (int j = 0; j < k; j++) {
  90.             if (i - 1 == j) A[i][j] = 1;
  91.             else A[i][j] = 0;
  92.         }
  93.     }
  94.     long long** b = malloc(k*sizeof(long long*));
  95.     for(int i = 0; i < k; i++){
  96.         b[i] = malloc(k*sizeof(long long));
  97.     }
  98.     mpow(A, N, k, p, b);
  99.     for(int i = 0; i < k; i++){
  100.         free(A[i]);
  101.     }
  102.     free(A);
  103. //    for (int i = 0; i < k; i++) {
  104. //        for (int j = 0; j < k; j++) {
  105. //            printf("%u ", b[i][j]);
  106. //        }
  107. //        printf("\n");
  108. //    }
  109.     long long variable = 0;
  110.     for (int i = 0; i < k; i++){
  111.         variable += b[0][i]*F[k-1-i];
  112.     }
  113.     printf("%lld", variable%p);
  114.     free(F);
  115.     for(int i = 0; i < k; i++){
  116.         free(b[i]);
  117.     }
  118.     free(b);
  119. }
Advertisement
Add Comment
Please, Sign In to add comment