希爾密碼編譯演算法(湖南師範大學第六屆大學生電腦程式設計競賽)hnuoj11552

來源:互聯網
上載者:User

標籤:湖南師範大學第六屆大學生電腦程式設計競   希爾解密   

解密

Time Limit: 1000ms, Special Time Limit:2500ms, Memory Limit:65536KB

Total submit users: 2, Accepted users: 0

Problem 11552 : No special judgement

Problem description

  密碼學中,有一種加密方法,叫做希爾加密法。其加密步驟如下: 
Step1:將待加密的字串s={s[0], s[1], …… ,s[n-1]} (為簡單起見,在本題中,字串s只含小寫字母)按a->0, b->1,c->2, ……, y->24, z->25的規則轉換為整形數組a={a[0], a[1], …… ,a[n-1]};
Step2: 將數組a分成長度相等的k個部分,每部分長度均為L(保證k*L=s待加密的字串s的長度)
Setp3:將每部分左乘一L * L矩陣A,將結果向量中所有值對26模數後替換原來的部分,得到新的數組 
b={b[0], b[1], …… ,b[n-1]}, 
即b中的元素滿足: 
(b[i * k],b[i * k + 1], ……, b[i * k + (L - 1)]) = (a[i * k],a[i * k + 1], ……, a[i * k + (L - 1)])*A
Step4:將數組b中的數按0->a, 1->b, 2->c, ……, 24->y, 25->z的規則轉換為密文 
例如:加密july,矩陣A=[11 8;3 7](分號表示另起一行)
Step1:將july轉化為數組a={9, 20, 11, 24};
Step2:將a分為{9, 20},{11, 24}兩部分 
Step3:由於[9, 20] * [11 8;3 7] = [159, 212]
[11, 24] * [11 8;3 7]=[193, 256]
故b=[159 % 26, 212 % 26, 193 % 26, 256 % 26] = [3, 4, 11, 22]
Step4:密文即為delw
你的任務是:給你密文和矩陣A,求原字串 

Input

  第一行為一個整數T (0 < T < 20), 表示資料的組數.
每組資料的第一行為一個 只有小寫字母構成的 加密後 的字串, 其長度不超過10000。
第二行為一個整數M(0 < M <= 100 且 字串的長度可以整除M),表示矩陣A是M*M的矩陣 
後面M行,每行M個整數, 表示矩陣A,輸入資料保證矩陣A主對角線上的元素與26互素

Output

  對每組資料,輸出一行,為密文所對應的原文

Sample Input

2

delw

2

11 8

3 7

pabqlzqii

3

1 14 2

5  9 2

4 7 3

Sample Output

july

qvtusjkcm

Problem Source

  HUNNU Contest 

 

 

希爾解密;需要先求逆矩陣;

我只能過第一組。。。。大神們,求解釋。。。

#include <math.h>#include <string.h>#include <malloc.h>#include <iostream>#include <iomanip>#include<stdio.h>using namespace std;#define  N  105                //定義方陣的最大階數為10//函數的聲明部分double MatDet(double *p, int n);                    //求矩陣的行列式double Creat_M(double *p, int m, int n, int k);    //求矩陣元素A(m, n)的代數餘之式void print(double *p, int n);                    //輸出矩陣n*nbool Gauss(double A[][N], double B[][N], int n);    //採用部分主元的高斯消去法求方陣A的逆矩陣Bdouble a[N][N],b[N][N];int c[N][N];double determ;                //定義矩陣的行列式//int zimu[26];int gcd(int a,int b){    if(!b) return a;    gcd(b,a%b);}void Print(int mm[],int k){    /*    for(int i=0; i<k; i++)    {        printf("%d ",mm[i]);    }    printf("\n");*/    for(int i=0; i<k; i++)    {        for(int j=0; j<k; j++)        {            printf("%d ",c[i][j]);        }        printf("\n");    }   // double tp[105]= {0};   int tp[105]={0};    for(int i=0; i<k; i++) //列    {        for(int j=0; j<k; j++) //行||mm的行        {            tp[i]+=mm[j]*c[j][i]; //           printf("tp=%d\tmm=%d\tb=%d\n",tp[i],mm[j],c[j][i]);        }    }    for(int i=0; i<k; i++)    { //       int tmp=(int)(tp[i]); //       printf("%d\t",tmp);        printf("%c",((tp[i])%26+26)%26+'a');  //      while(tp[i]<0) tp[i]+=26;  //      printf("%c\n",(int)(tp[i])%26+'a');    } //   printf("\n");}int main(){ //   freopen("xier.txt","r",stdin);    double *buffer, *p;            //定義數組首地址指標變數    int row, num;                //定義矩陣的行數和矩陣元素個數   // int i, j;    int n;//    for(int i=0;i<26;i++)//       zimu[i]=i;    int T,len,M,mo[105];    char mi[10005];    scanf("%d",&T);    while(T--)    {        scanf("%s",mi);        len=strlen(mi);        scanf("%d",&n);        row=n;        num = 2*row*row;        buffer = (double *)calloc(num, sizeof(double));        //分配記憶體單元        p = buffer;        for(int i=0; i<n; i++)        {            for(int j=0; j<n; j++)            {                scanf("%lf",&a[i][j]);                *p++=a[i][j];            }        }        determ = MatDet(buffer, row);    //求整個矩陣的行列式  //      printf("determ=%lf\n",determ);        int d=gcd((int)(determ),27);        d=(int)determ*27/d; //       printf("***************************************d=%d\n",d);        for (int i = 0; i < row; i++)    //求逆矩陣        {            for (int j = 0; j < row; j++)            {                *(p+j*row+i) = Creat_M(buffer, i, j, row)*d/determ;            }        }        print(p, row);        free(buffer);        //釋放記憶體空間        for(int i=0; i<len; i++)            {                //    printf("mi=%c\n",mi[i]);                mo[i%n]=mi[i]-'a';                //         printf("i=%d\tmo=%d\n",i%n,mo[i%n]);                if((i+1)%n==0) Print(mo,n);            }            printf("\n"); //       for(int i=0; i<n; i++) //       {  //          for(int j=0; j<n; j++)   //         {   //             printf("%lf ",a[i][j]);    //        }    //        printf("\n");    //    } //       if(Gauss(a,b,n)) //       {            /*            for (int i = 0; i < n; i++)            {                cout << setw(4);                for (int j = 0; j < n; j++)                {                    cout << b[i][j] << setw(10);                }                cout << endl;            }*/   //     }    }    return 0;}//-----------------------------------------------//功能: 求矩陣(n*n)的行列式//入口參數: 矩陣的首地址,矩陣的行數//傳回值: 矩陣的行列式值//----------------------------------------------double MatDet(double *p, int n){    int r, c, m;    int lop = 0;    double result = 0;    double mid = 1;    if (n != 1)    {        lop = (n == 2) ? 1 : n;            //控制求和迴圈次數,若為2階,則迴圈1次,否則為n次        for (m = 0; m < lop; m++)        {            mid = 1;            //順序求和, 主對角線元素相乘之和            for (r = 0, c = m; r < n; r++, c++)            {                mid = mid * (*(p+r*n+c%n));            }            result += mid;        }        for (m = 0; m < lop; m++)        {            mid = 1;            //逆序相減, 減去次對角線元素乘積            for (r = 0, c = n-1-m+n; r < n; r++, c--)            {                mid = mid * (*(p+r*n+c%n));            }            result -= mid;        }    }    else        result = *p;    return result;}//----------------------------------------------------------------------------//功能: 求k*k矩陣中元素A(m, n)的代數餘之式//入口參數: k*k矩陣的首地址,矩陣元素A的下標m,n,矩陣行數k//傳回值: k*k矩陣中元素A(m, n)的代數餘之式//----------------------------------------------------------------------------double Creat_M(double *p, int m, int n, int k){    int len;    int i, j;    double mid_result = 0;    int sign = 1;    double *p_creat, *p_mid;    len = (k-1)*(k-1);            //k階矩陣的代數餘之式為k-1階矩陣    p_creat = (double*)calloc(len, sizeof(double)); //分配記憶體單元    p_mid = p_creat;    for (i = 0; i < k; i++)    {        for (j = 0; j < k; j++)        {            if (i != m && j != n) //將除第i行和第j列外的所有元素儲存到以p_mid為首地址的記憶體單元            {                *p_mid++ = *(p+i*k+j);            }        }    }    sign = (m+n)%2 == 0 ? 1 : -1;    //代數餘之式前面的正、負號    mid_result = (double)sign*MatDet(p_creat, k-1);    free(p_creat);    return mid_result;}//-----------------------------------------------------//功能: 列印n*n矩陣//入口參數: n*n矩陣的首地址,矩陣的行數n//傳回值: 無傳回值//-----------------------------------------------------void print(double *p, int n){    int i, j;    for (i = 0; i < n; i++)    {   //     cout << setw(4);        for (j = 0; j < n; j++)        {            c[i][j]=(int)*p++;            while(c[i][j]<0) c[i][j]+=26;   //         cout << setiosflags(ios::right) << *p++ << setw(10);        }   //     cout << endl;    }}//------------------------------------------------------------------//功能: 採用部分主元的高斯消去法求方陣A的逆矩陣B//入口參數: 輸入方陣,輸出方陣,方陣階數//傳回值: true or false//-------------------------------------------------------------------bool Gauss(double A[][N], double B[][N], int n){    int i, j, k;    double max, temp;    double t[N][N];                //臨時矩陣    //將A矩陣存放在臨時矩陣t[n][n]中    for (i = 0; i < n; i++)    {        for (j = 0; j < n; j++)        {            t[i][j] = A[i][j];        }    }    //初始化B矩陣為單位陣    for (i = 0; i < n; i++)    {        for (j = 0; j < n; j++)        {            B[i][j] = (i == j) ? (double)1 : 0;        }    }    for (i = 0; i < n; i++)    {        //尋找主元        max = t[i][i];        k = i;        for (j = i+1; j < n; j++)        {            if (fabs(t[j][i]) > fabs(max))            {                max = t[j][i];                k = j;            }        }        //如果主元所在行不是第i行,進行行交換        if (k != i)        {            for (j = 0; j < n; j++)            {                temp = t[i][j];                t[i][j] = t[k][j];                t[k][j] = temp;                //B伴隨交換                temp = B[i][j];                B[i][j] = B[k][j];                B[k][j] = temp;            }        }        //判斷主元是否為0, 若是, 則矩陣A不是滿秩矩陣,不存在逆矩陣        if (t[i][i] == 0)        {            cout << "There is no inverse matrix!";            return false;        }        //消去A的第i列除去i行以外的各行元素        temp = t[i][i];        for (j = 0; j < n; j++)        {            t[i][j] = t[i][j] / temp;        //主對角線上的元素變為1            B[i][j] = B[i][j] / temp;        //伴隨計算        }        for (j = 0; j < n; j++)        //第0行->第n行        {            if (j != i)                //不是第i行            {                temp = t[j][i];                for (k = 0; k < n; k++)        //第j行元素 - i行元素*j列i行元素                {                    t[j][k] = t[j][k] - t[i][k]*temp;                    B[j][k] = B[j][k] - B[i][k]*temp;                }            }        }    }    for(int i=0; i<n; i++)    {        for(int j=0; j<n; j++)        {            B[i][j]*=determ;        }        //printf("\n");    }    return true;}


 

 

 

希爾密碼編譯演算法(湖南師範大學第六屆大學生電腦程式設計競賽)hnuoj11552

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.