POJ 3233 Matrix Power Series

64 篇文章 0 订阅
23 篇文章 0 订阅
 转至:http://blog.csdn.net/wohenlaoshia/archive/2008/08/07/2784489.aspx
Matrix Power Series
Time Limit: 3000MSMemory Limit: 131072K
Total Submissions: 1904Accepted: 597

Description

Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak.

Input

The input contains exactly one test case. The first line of input contains three positive integers n (n ≤ 30), k (k ≤ 109) and m (m < 104). Then follow n lines each containing n nonnegative integers below 32,768, giving A’s elements in row-major order.

Output

Output the elements of S modulo m in the same way as A is given.

Sample Input

2 2 4
0 1
1 1

Sample Output

1 2
2 3

Source

POJ Monthly--2007.06.03, Huang, Jinsong
 
给定n*n矩阵,计算A + A^2 +....+A^n的值。
                              A        I                                      A^(k+1)      I+A+.....+A^k
构造矩阵 B   =                         ,易得B^(k+1) =                                                       ,所以问题转化为求B^(k+1),计算可知,在B(A,I,0,I)
                              0         I                                      0                  I
中,(0,I)不影响(A,I)的值,所以矩阵B可以简化为B(A,I),假设C(A,B)是C(A,B,0,I)的简化,则C的乘法可定义为C*C=(A^2,A*B+B),固由此可推出B(A,I)的乘法定义。
 
  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. int n, m;
  5. struct multiply {
  6.     int a[31][62];
  7.     multiply operator*(const multiply & l) {
  8.         multiply temp;
  9.         int i, j, k;
  10.         memset(temp.a, 0, sizeof (temp.a));
  11.         for (i = 0; i < n; i++)
  12.             for (j = 0; j < n; j++)
  13.                 for (k = 0; k < n; k++)
  14.                     temp.a[i][j] = (temp.a[i][j] + a[i][k] * l.a[k][j]) % m;
  15.         for (i = 0; i < n; i++)
  16.             for (j = n; j < 2 * n; j++) {
  17.                 temp.a[i][j] = (temp.a[i][j] + l.a[i][j]) % m;
  18.                 for (k = 0; k < n; k++)
  19.                     temp.a[i][j] = (temp.a[i][j] + l.a[i][k] * a[k][j]) % m;
  20.             }
  21.         return temp;
  22.     }
  23. } K;
  24. multiply pow(multiply & t, int k) {
  25.     multiply temp;
  26.     if (k == 1) return t;
  27.     temp = t * t;
  28.     if (k & 1) return pow(temp, k / 2) * t;
  29.     else return pow(temp, k / 2);
  30. }
  31. int main() {
  32.     multiply ss;
  33.     int k, i, j;
  34.     scanf("%d%d%d", &n, &k, &m);
  35.     for (i = 0; i < n; i++) {
  36.         for (j = 0; j < n; j++) {
  37.             scanf("%d", &K.a[i][j]);
  38.         }
  39.     }
  40.     for (i = 0, j = n; i < n; i++, j++) {
  41.         K.a[i][j] = 1;
  42.     }
  43.     ss = pow(K, k + 1);
  44.     for (i = 0, j = n; i < n; i++, j++) {
  45.         ss.a[i][j]--;
  46.     }
  47.     for (i = 0; i < n; i++) {
  48.         for (j = n; j < 2 * n - 1; j++)
  49.             printf("%d ", ss.a[i][j] % m);
  50.         printf("%d/n", ss.a[i][j] % m);
  51.     }
  52.     return 0;
  53. }

Time: 141MS

Memory: 1104K

 

===============================================================================================

学习到了原来二分是好东东的说-_____________-

这里附上自己的代码,感受到了和大牛的差距也...

T.T偶500+MS啊,差距也....

  1. #include <iostream>
  2. using namespace std;
  3. #define MAX_SIZE 30
  4. int moudle,k,size;
  5. struct Mat
  6. {
  7.     long long g[MAX_SIZE][MAX_SIZE];
  8.     Mat operator+(const Mat&a)
  9.         {
  10.             Mat temp;
  11.             int i,j;
  12.             for(i=0;i<size;i++)
  13.                 for(j=0;j<size;j++)
  14.                     temp.g[i][j]=(g[i][j]+a.g[i][j])%moudle;
  15.             return temp;
  16.         }
  17.     Mat operator*(const Mat&a)
  18.         {
  19.             Mat temp;
  20.             int i,j,k;
  21.             for(i=0;i<size;i++)
  22.                 for(j=0;j<size;j++)
  23.                 {
  24.                     temp.g[i][j]=0;
  25.                     for(k=0;k<size;k++)
  26.                         temp.g[i][j]+=g[i][k]*a.g[k][j];
  27.                     if(temp.g[i][j]>=moudle)
  28.                         temp.g[i][j]%=moudle;
  29.                 }
  30.             return temp;
  31.         }
  32. }A,S;
  33. Mat pow(int _k,Mat g)
  34. {
  35.     Mat temp;
  36.         int i,j;
  37.         for(i=0;i<size;i++)for(j=0;j<size;j++)if(i!=j)temp.g[i][j]=0;else temp.g[i][j]=1;
  38.     for(;_k;g=g*g,_k>>=1)
  39.           if(_k&1)temp=temp*g;
  40.    return temp;
  41. }
  42. Mat sum(int _k)
  43. {
  44.     if(_k==1) return A;
  45.     Mat temp,tpow;
  46.     temp=sum(_k/2);
  47.     if(_k&1)
  48.         temp=temp+temp*(tpow=pow(_k/2+1,A))+tpow;
  49.     else
  50.         temp=temp+pow(_k/2,A)*temp;
  51.     return temp;
  52. }
  53. int main()
  54. {
  55.     int i,j;
  56.     scanf("%d%d%d",&size,&k,&moudle);
  57.     for(i=0;i<size;i++)
  58.         for(j=0;j<size;j++)
  59.             scanf("%d",&A.g[i][j]);
  60.     S=sum(k);
  61.     for(i=0;i<size;i++)
  62.     {
  63.         for(j=0;j<size-1;j++)
  64.             printf("%d ",S.g[i][j]);
  65.         printf("%d/n",S.g[i][size-1]);
  66.     }
  67.     return 0;
  68. }

    • 0
      点赞
    • 0
      收藏
      觉得还不错? 一键收藏
    • 5
      评论
    评论 5
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值