• 蓝桥杯 矩阵乘方 矩阵快速幂


    问题描述
      给定一个矩阵A,一个非负整数b和一个正整数m,求A的b次方除m的余数。
      其中一个nxn的矩阵除m的余数得到的仍是一个nxn的矩阵,这个矩阵的每一个元素是原矩阵对应位置上的数除m的余数。
      要计算这个问题,可以将A连乘b次,每次都对m求余,但这种方法特别慢,当b较大时无法使用。下面给出一种较快的算法(用A^b表示A的b次方):
      若b=0,则A^b%m=I%m。其中I表示单位矩阵。
      若b为偶数,则A^b%m=(A^(b/2)%m)^2%m,即先把A乘b/2次方对m求余,然后再平方后对m求余。
      若b为奇数,则A^b%m=(A^(b-1)%m)*a%m,即先求A乘b-1次方对m求余,然后再乘A后对m求余。
      这种方法速度较快,请使用这种方法计算A^b%m,其中A是一个2x2的矩阵,m不大于10000。
    输入格式
      输入第一行包含两个整数b, m,第二行和第三行每行两个整数,为矩阵A。
    输出格式
      输出两行,每行两个整数,表示A^b%m的值。
    样例输入
    2 2
    1 1
    0 1
    样例输出
    1 0
    0 1
    这是一个悲伤的故事,小细节导致的的严重后果。
    看到这道题疯狂暗示了应该使用矩阵快速幂,然后我就把我以前用过的矩阵快速幂模板拿过来改了改,https://www.cnblogs.com/fx1998/p/12618125.html
    然后发现改不对QAQ,然后又重新学了一遍矩阵快速幂。
    然后发现是我取模操作的一个细节错了_orz_
    改了这个细节后,直接从30分飙到100分。
    AC代码
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int b, p;
     4 struct Mat {
     5     int m[2][2];
     6 } ans, base; //ans为答案矩阵, base为需要求次方的矩阵 
     7 Mat Mul(Mat x, Mat y) { //返回矩阵x乘以矩阵y的矩阵 
     8     Mat c;
     9     for (int i = 0; i < 2; i++) {
    10         for (int j = 0; j < 2; j++) {
    11             c.m[i][j] = 0;
    12             for (int k = 0; k < 2; k++) {
    13                 c.m[i][j] += (x.m[i][k] % p * y.m[k][j] % p) % p;
    14             }
    15         }
    16     }
    17     return c;
    18 }
    19 void quick_pow(int n) { //求base的n次方 
    20     if (n == 0) {
    21         ans.m[0][0] = 1 % p, ans.m[0][1] = 0 % p, ans.m[1][0] = 0 % p, ans.m[1][1] = 1 % p;
    22     }
    23     while (n) { //同一般的快速幂 
    24         if (n & 1) {
    25             ans = Mul(ans, base);
    26         }
    27         base = Mul(base, base);
    28         n >>= 1;
    29     }
    30 }
    31 int main() {
    32     cin >> b >> p;
    33     ans.m[0][0] = 1, ans.m[0][1] = 0, ans.m[1][0] = 0, ans.m[1][1] = 1; //初始化ans为单位矩阵
    34     for (int i = 0; i < 2; i++) {
    35         for (int j = 0; j < 2; j++) {
    36             cin >> base.m[i][j]; //将base初始化为要求n次幂的矩阵
    37         }
    38     }
    39     quick_pow(b);
    40     for (int i = 0; i < 2; i++) {
    41         for (int j = 0; j < 2; j++) {
    42             cout << ans.m[i][j] % p << " ";
    43         }
    44         cout << endl;
    45     }
    46     return 0;
    47 }
  • 相关阅读:
    ini_set /ini_get函数功能-----PHP
    【转】那个什么都懂的家伙
    word 2007为不同页插入不同页眉页脚
    August 26th 2017 Week 34th Saturday
    【2017-11-08】Linux与openCV:opencv版本查看及库文件位置等
    August 25th 2017 Week 34th Friday
    August 24th 2017 Week 34th Thursday
    August 23rd 2017 Week 34th Wednesday
    August 22nd 2017 Week 34th Tuesday
    August 21st 2017 Week 34th Monday
  • 原文地址:https://www.cnblogs.com/fx1998/p/12686115.html
Copyright © 2020-2023  润新知