• POJ3233 Matrix Power Series


      原题传送:http://poj.org/problem?id=3233

      两个二分:二分 k ,二分矩阵。

      求Sn = A + A2 + A3 + … + Ak

      首先我们能矩阵二分快速幂计算出Ak,那么我们对S再进行二分:

      当k % 2 != 0则计算Ak+S(k-1),当k % 2 == 0时计算S(k/2) * (Ak/2 + E),这样就可以在log(k)的时间里算出Sk

      ps:这题有两个地方要注意,否则可能会TLE

      1. 用 unsigned int,不要 long long

      2. 取模运算效率很低,矩阵乘法单个元素最大值不是很大的情况下先算出来再取一次模更好。

    View Code 200ms左右
     1 #include <stdio.h>
     2 #include <string.h>
     3 const int maxn = 31;
     4 struct mat
     5 {
     6     unsigned m[maxn][maxn];
     7 }a, E;
     8 unsigned n, k, MOD;
     9 
    10 mat operator *(mat u, mat v)
    11 {
    12     mat c;
    13     memset(c.m, 0, sizeof c.m);
    14     for(int i = 0; i < n; i ++)
    15         for(int j = 0; j < n; j ++){
    16             for(int r = 0; r < n; r ++)
    17                 c.m[i][j] += u.m[i][r] * v.m[r][j]; 
    18             c.m[i][j] %= MOD;
    19         }
    20     return c;
    21 }
    22 
    23 mat operator +(mat u, mat v)
    24 {
    25     mat c;
    26     for(int i = 0; i < n; i ++)
    27         for(int j = 0; j < n; j ++)
    28             c.m[i][j] = (u.m[i][j] + v.m[i][j]) % MOD;
    29     return c;
    30 }
    31 
    32 mat cal(mat A, int x)
    33 {
    34     mat t = E;
    35     for(; x; x >>= 1, A = A * A)
    36         if(x & 1) t = t * A;
    37     return t;
    38 }
    39 
    40 mat sum(int x)
    41 {
    42     if(x == 1)
    43         return a;
    44     if(x & 1)
    45         return cal(a, x) + sum(x - 1);
    46     else
    47         return sum(x / 2) * (E + cal(a, x / 2));
    48     return a;
    49 }
    50 int main()
    51 {
    52     while(scanf("%d%d%d", &n, &k, &MOD) != EOF)
    53     {
    54         for(int i = 0; i < n; i ++)
    55         {
    56             for(int j = 0; j < n; j ++)
    57             {
    58                 scanf("%u", &a.m[i][j]);
    59                 a.m[i][j] %= MOD;
    60                 E.m[i][j] = (i == j);
    61             }
    62         }
    63         mat ans = sum(k);
    64         for(int i = 0; i < n; i ++)
    65         {
    66             for(int j = 0; j < n-1; j ++)
    67                 printf("%u ", ans.m[i][j]);
    68             printf("%u\n", ans.m[i][n - 1]);
    69         }
    70     }
    71     return 0;
    72 }
  • 相关阅读:
    13、文件修改及函数的基本使用
    12、文件处理 b模式
    作业3月16号
    作业3月13号
    11、文件处理 t模式
    10、数据类型内置之集合
    作业3月11号
    9、基础类型之列表、元组、字典
    作业3月10号
    8、for循环以及数字类型和字符串类型的内置方法
  • 原文地址:https://www.cnblogs.com/huangfeihome/p/2836389.html
Copyright © 2020-2023  润新知