1402Vigenère密碼(Noip2012提高組第1題)
阿新 • • 發佈:2017-12-08
http gets 實現 dst 圖片 strong 註意 大小 math.h
維吉尼亞密碼:人們在單一愷撒密碼的基礎上擴展出多表密碼,稱為“維吉尼亞”密碼。該方法最早記錄在吉奧萬·巴蒂斯塔·貝拉索( Giovan Battista Bellaso)於1553年所著的書《吉奧萬·巴蒂斯塔·貝拉索先生的密碼》(意大利語:La cifra del. Sig. Giovan Battista Bellaso)中。
我大概花了1.5h寫出的代碼,老同誌寫代碼慢,你們寫估計40-50min↓↓↓↓ 缺點:審題不清,代碼量大,算法不夠嚴謹,代碼運行時間長。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 using namespace std; 6 char a[30][30]; 7 char k[1200],m[1200]; 8 /*step3:密鑰和密文來查找明文函數的編寫*/ 9 char chazhao(char c1,char c2) 10 { 11 int x,y; 12 //下面循環實現行查找 13 for(int i=1;i<=26;i++) 14 { 15 if(a[i][1]==toupper(c1)) 16 { 17 x=i;18 break; 19 } 20 } 21 //下面循環實現通過行號和密文結果來找明文 22 for(int i=1;i<=26;i++) 23 { 24 if(a[x][i]==toupper(c2)) 25 { 26 y=i; 27 break; 28 } 29 } 30 //大小寫對應 31 if(c2>=‘A‘&&c2<=‘Z‘)return char(‘A‘+y-1); 32else return char(‘a‘+y-1); 33 } 34 int main() 35 { 36 char c=‘A‘; 37 for(int i=1;i<=26;i++) 38 { 39 for(int j=1;j<=26;j++) 40 { 41 a[i][j]=c; 42 c++; 43 if(c==‘[‘)c=‘A‘; 44 } 45 c++; 46 if(c==‘[‘)c=‘A‘; 47 } 48 /*step1:構造運算規則表,完成之後可以單獨測試*/ 49 gets(k); 50 gets(m); 51 int lk=strlen(k),lm=strlen(m); 52 int kk=lk,n=0; 53 while(kk<lm) 54 { 55 k[kk++]=k[n++]; 56 if(n==lk)n=0; 57 } 58 /*step2:讓密鑰和密文長度一樣的放在兩個數組中,這樣就可以方便下一步一次循環實現*/ 59 for(int i=0;i<lm;i++)cout<<chazhao(k[i],m[i]); 60 return 0; 61 }
網上其他題解↓↓↓↓↓↓↓簡短,代碼量少。。。算法嚴謹
本表指 一對密鑰與原文可以加密成密文,現在要翻譯密文,也就是知道對應的點,也知道了y軸坐標,求x軸坐標。
1.當密文≥密鑰時,我們發現數據是依次遞增的,則此時ans[i]= miwen[i]-key[j]+‘a‘
2.當密文<密鑰時,數據由最右端向左依次遞減,此時ans[i]= ‘z‘-(key[j]-miwen[i]-1)
j的意義在後面。
註意這裏還有一個易錯點,密鑰的長度可能小於密文的長度,那麽當密鑰較短時就要運用循環多次使用此密鑰
int j=0;
並且在每次循環後
j++;
if(j==strlen(key))
j=0;
最後通過miwen_x[i]的值將原文的大小寫形式恢復原樣
這樣就解決此問題了
本題總思路:
1.讀入密鑰、密文並轉換成小寫(大寫也可),同時記錄密文的大小寫情況
2. 運用算法算出原文
3.通過大小寫情況恢復原文的大小寫
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> int change(int i)//大小寫轉換 { return (i>=‘A‘&&i<=‘Z‘)?i+‘a‘-‘A‘:i; } int main() { char key[120]; char miwen[1200]; int miwen_x[1200];//密文大小寫 1小寫 2大寫 scanf("%s %s",key,miwen); int len=strlen(key); for(int i=0;i<=len-1;i++) key[i]=change(key[i]); for(int i=0;i<=strlen(miwen)-1;i++) { if(miwen[i]>=‘A‘&&miwen[i]<=‘Z‘) miwen_x[i]=2; else miwen_x[i]=1; miwen[i]=change(miwen[i]); } char ans[1200]; int j=0; for(int i=0;i<=strlen(miwen)-1;i++) { if(miwen[i]>=key[j]) ans[i]=miwen[i]-key[j]+‘a‘; else ans[i]=‘z‘-(key[j]-miwen[i]-1); if(miwen_x[i]==2) ans[i]=ans[i]-(‘a‘-‘A‘); j++; if(j==len) j=0; } ans[strlen(miwen)]=0; printf("%s",ans); return 0; }View Code
敲黑板結論:讀題規劃算法比寫代碼更重要。。。
1402Vigenère密碼(Noip2012提高組第1題)