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 }