#include <iostream> #include <vector> #include<string.h> #include<stdio.h> #define N 5 using namespace std; int exgcd(int A,int &x,int B,int &y) { int x1,y1,x0,y0; x0=1;y0=0; x1=0;y1=1; int r=(A%B+B)%B; int q=(A-r)/B; x=0;y=1; while(r) { x=x0-q*x1; y=y0-q*y1; x0=x1; y0=y1; x1=x;y1=y; A=B;B=r;r=A%B; q=(A-r)/B; } return B; } int modq(int a,int n,int x,int y) { int b=1; int d=exgcd(a,x,n,y); if(b%d==0) { x=(x%(n/d)+n/d)%(n/d); if(!x)x++; return x; } else printf("Not Exist "); } //计算矩阵的行列式 int getA(int A[N][N],int n) { if(n==1) return A[0][0]; int num=0; int temp[N][N]={0.0}; int i,j,k; for(i=0;i<n;i++) { for(j=0;j<n-1;j++) { for(k=0;k<n-1;k++) { if(k>=i) temp[j][k]=A[j+1][k+1]; else temp[j][k]=A[j+1][k]; } } int t=getA(temp,n-1); if(i%2==0) num+=A[0][i]*t; else num-=A[0][i]*t; } return num%26; } //求矩阵的伴随矩阵 void getAstart(int A[N][N],int n,int newA[N][N]) { if(n==1) { newA[0][0]=1; return; } int i,j,k,t; int temp[N][N]; for(i=0;i<n;i++) { for(j=0;j<n;j++) { for(k=0;k<n-1;k++) { for(t=0;t<n-1;t++) { temp[k][t]=A[(k>=i)?k+1:k][(t>=j)? t+1:t]; } } newA[j][i]=(getA(temp,n-1)); if((i+j)%2==1) newA[j][i]=-newA[j][i]; newA[j][i]=newA[j][i]%26; if(newA[j][i]<0) newA[j][i]=(newA[j][i]+26)%26; } } } //求矩阵的逆 void getInverse(int A[N][N],int n,int I[N][N]) { int t[N][N]={0.0}; int flag=getA(A,n); int x,y; int e=modq(flag,26,x,y); if(e==0) return; else { getAstart(A,n,t); for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { I[i][j]=(t[i][j]*e)%26; if(I[i][j]<0) I[i][j]=(I[i][j]+26)%26; } } } } int gcd(int m,int n) { int r=0; if(m==0||n==0) return 0; if(m==1||n==1) return 1; else { if(n>m) { int s=m; m=n;n=s; } r=m%n; while(r!=0) { m=n; n=r; r=m%n; if(r==0) { return n; } } } } bool IsInverse(int A[N][N],int n)//判断矩阵是否可作为密钥 { int t=getA(A,n); if(gcd(t,26)==1) return true; else return false; } vector<int> change1(string s) //将明文密文转化为字母表中的次序,A为0,依次类推 { vector<int>v; for(int i=0;i<s.size();i++) { if(s[i]>='A'&&s[i]<='Z') v.push_back(s[i]-'A'); if(s[i]>='a'&&s[i]<='z') v.push_back(s[i]-'a'); } return v; } string change2(vector<int>v)//将字母的次序转化为小写字母 { string s=""; for(int i=0;i<v.size();i++) { char a=v[i]+97; s+=a; } return s; } string change3(vector<int>v)//将字母的次序转化为大写字母 { string s=""; for(int i=0;i<v.size();i++) { char a=v[i]+65; s+=a; } return s; } //对明文进行加密 void addcode(int A[N][N],string s){ int length=s.length(); vector<int> mingnum; mingnum=change1(s); int rows=length/N; int lines=N; int mingmatrix[rows][lines]={0.0}; for(int i=0;i<length;i++){ mingmatrix[i/5][i%5]=mingnum[i]; } int mimatrix[rows][lines]={0.0}; for(int i=0;i<rows;i++){ for(int j=0;j<lines;j++){ int temp=0; for(int k=0;k<lines;k++){ temp+=mingmatrix[i][k]*A[k][j]; } mimatrix[i][j]=temp%26; } } vector<int> minum; for(int i=0;i<rows;i++){ for(int j=0;j<lines;j++){ minum.push_back(mimatrix[i][j]); } } string miwen=change2(minum); cout<<"得到的密文"<<miwen<<endl; } void deaddcode(int A[N][N],string s){ int D[N][N]={0.0}; getInverse(A,5,D); int length=s.length(); vector<int> minum; minum=change1(s); int rows=length/N; int lines=N; int mimatrix[rows][lines]={0.0}; for(int i=0;i<length;i++){ mimatrix[i/5][i%5]=minum[i]; } int mingmatrix[rows][lines]={0.0}; for(int i=0;i<rows;i++){ for(int j=0;j<lines;j++){ int temp=0; for(int k=0;k<lines;k++){ temp+=mimatrix[i][k]*D[k][j]; } mingmatrix[i][j]=temp%26; } } vector<int> mingnum; for(int i=0;i<rows;i++){ for(int j=0;j<lines;j++){ mingnum.push_back(mingmatrix[i][j]); } } string mingwen=change2(mingnum); cout<<"得到的明文"<<mingwen<<endl; } int main() { cout<<"请输入一个5阶密钥矩阵"<<endl; int ars[5][5]; for(int i=0;i<5;i++){ cout<<"第"<<i+1<<"行"<<endl; for(int j=0;j<5;j++){ cin>>ars[i][j]; } } cout<<"请输入明文"<<endl; string mess; cin>>mess; addcode(ars,mess); cout<<"请输入密文"<<endl; string code; cin>>code; deaddcode(ars,code); }
其实老师让做的是变长的,我找了网上的代码,加密解密和它做的略有不同,不过除非是希尔加密否则求行列式不推荐这种做法,因为循环到了三层以上代码的可读性非常差,但是用这种方法求行列式的好处就是比较简单,推荐传一个二级指针进去进行行列式求解,较好理解,但对于希尔加密不适合,因为会在判断互素的时候损失精度。