Z256上的矩阵 的 快速乘幂算法 C

碎碎念:

之前一直把算法理解错了,改了很久还是没改对

这是个教训啊!

以后一定要先把算法检查正确了再开始敲,盲目开敲只能浪费时间!

这里是为了完成作业,作业的要求是C语言。。

会用python再实现一遍 再贴代码

C++之前写过类似的Matrix类,但是丢了,不想再实现一遍了,所以不会再用C++写了。。

 

 

快速乘幂算法的原理很简单~

这里也只是把数->矩阵,而且把数限定在0-255之间了,这些都是很好实现的!

 

快速乘幂算法:m^e,

  e=ak*2^k+ak-1*2^(k-1)+……+a0*2^0

 也就是

m^e=((……(m^ak)^2 * m^ak-1……)^2 * m^a1)^2 * m^a0

两个临时变量V (结果),T(保存m^i)。

step1:将e表示成2进制,化成e=2^k[n]+2^k[n-1]……+2^[0]

   这是很好化的 只需要循环取余数+除下去就好了,就不介绍了:

      这里我用了一个函数

 1 void tobinary(int e,int&n,unsigned char k[])
 2 { 
 3     n=0;
 4     while(e!=0)
 5     {
 6     
 7         k[n]=e%2;
 8         e=e/2;
 9         n++;
10     } 
11 }

 

step2 初始化:

  if(k[0]==1) 
    V=A;
   else V=1;  

step3 就是主要的步骤啦

  for(int i=1;i<n;i++)
   {
      T=T*T
      if(k[i]==1)
      {  
          V=V*T;
      }
   }

 

 

全部代码

  1 #include <stdio.h>
  2 #include <conio.h>
  3 #include <string.h>
  4 #include <stdlib.h>
  5 #include <time.h>
  6 #include <sys/timeb.h>
  7 
  8 #define MOD 256
  9 #define N 4 
 10 
 11 void Copy(unsigned char A[N][N],unsigned char B[N][N])  //N*N 矩阵复制A=B
 12 {
 13     for(unsigned i=0;i<N;i++)
 14     {
 15         for(unsigned j=0;j<N;j++)
 16         {
 17            A[i][j]= B[i][j];
 18         }
 19     }
 20 }
 21 
 22 
 23 void Output(unsigned char m[N][N]) // 输出N*N矩阵m
 24 {
 25     for(unsigned i=0;i<N;i++)
 26     {
 27         for(unsigned j=0;j<N;j++)
 28         {
 29             printf("% -5u ",m[i][j]);
 30         }
 31         putchar('\n');
 32     }
 33     putchar('\n');
 34 }
 35 
 36 
 37 void tobinary(int e,int&n,unsigned char k[])
 38 { 
 39     n=0;
 40     while(e!=0)
 41     {
 42     
 43         k[n]=e%2;
 44         e=e/2;
 45         n++;
 46     } 
 47 }
 48 
 49 void Multiply(unsigned char a[N][N],unsigned char b[N][N],unsigned char v[N][N])  // N*N 矩阵相乘,v <- a*b
 50 {
 51     unsigned char V[N][N]; 
 52     for(unsigned i=0;i<N;i++)
 53     {
 54         for(unsigned j=0;j<N;j++)
 55         {
 56             for(unsigned k=V[i][j]=0;k<N;k++)
 57             {
 58                 V[i][j] = (V[i][j]+a[i][k]*b[k][j])%MOD;
 59             }
 60         }
 61     }
 62     Copy(v,V); 
 63 }
 64 
 65 
 66 void SetE(unsigned char A[N][N]) //A=E 
 67 { 
 68     for(int i=0;i<N;i++)
 69     {
 70         for(int j=0;j<N;j++)
 71         {
 72             if(i==j) A[i][j]=1;
 73             else A[i][j]=0;
 74         }
 75     }
 76 }
 77 
 78 
 79 void GetMat(unsigned char M[N][N])           //随机生成N*N矩阵并输出
 80 {
 81     printf("\n随机寻找 Z%u 上的 %u*%u 矩阵 M.\n",MOD,N,N);
 82 
 83     for(unsigned char i=0;i<N;i++)
 84         for(unsigned char j=0;j<N;j++)
 85             M[i][j] = rand()%MOD;
 86     Output(M);
 87 }
 88 
 89 
 90 void QuickPow(int e,unsigned char A[N][N],unsigned char v[N][N])//快速乘幂 
 91 {
 92     printf("\n矩阵M 在Z%d的%d次幂:\n",MOD,e);
 93     unsigned char k[2000];
 94     int n=0;
 95     tobinary(e,n,k);
 96     //for(int i=0;i<n;i++) printf("\nk%d = %d    \n",i ,k[i]);
 97     unsigned char V[N][N];
 98     
 99     if(k[0]==1) 
100         Copy(V,A);
101     else SetE(V);
102     
103     unsigned char T[N][N];
104     Copy(T,A);//T=V
105     //printf("n=%d",n);
106     for(int i=1;i<n;i++)
107     {
108         Multiply(T,T,T);//T=T*T
109         if(k[i]==1) 
110         {
111             Multiply(V,T,V);
112         }
113     }
114     Copy(v,V);
115 } 
116  
117 int main(){
118     srand((unsigned)time(NULL));
119     unsigned char A[N][N];
120     unsigned char R[N][N];
121     printf("快速乘幂:\n");
122     int e=rand()%MOD;
123     printf("e=%d",e);
124     GetMat(A);
125     QuickPow(e,A,R);
126     Output(R);
127 
128     //QuickPow(3,A,M);
129     //Multiply(A,M,R);
130     //Output(R);
131     
132 }

 

posted @ 2016-11-12 15:05  保暖婆婆  阅读(429)  评论(0编辑  收藏  举报