小測驗:解密文件——題解

因爲題面複製不下來,所以咱們簡化題面。

我們知道字母出現的概率(大寫字母視爲小寫字母),現在給一個加密後的文章,文章只有標點,大小寫字母和空格。
加密的規則如下:
0<=k<26,a-z編號爲0-25,將字母i替換爲(i+k)mod26,原來是大寫字母的還是大寫字母,原來是小寫字母的還是小寫字母。
你需要枚舉k,選擇一個使得最後文章的字母概率與原先字母概率之差的平方和最小的k,如果有多個這樣的k,則k越小越好。
最後輸出解密出的文件。

這題……我就不說什麼了吧……
純粹模擬,注意兩點
1.讀入數據
2.枚舉
沒了,就這樣
代碼很長……就這樣

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
double p[27]={0};
char a[1000000];
int tong[27]={0};
double tp[27]={0};
double minn=999999999;
int zuik;
void suan(int k){
    double fang=0;
    for(int i=0;i<=25;i++){
        fang+=pow((p[i]-tp[i]),2);
    }
    if(minn>fang){
        minn=fang;
        zuik=k;
    }
    return;
}
int main(){
    freopen("decode.in","r",stdin);
    freopen("decode.out","w",stdout);
    for(int i=0;i<=25;i++){
        scanf("%lf\n",&p[i]);
    }
    int l=0;
    while(scanf("%c",&a[l])!=EOF){
        l++;
    }
    l--;
    /*for(int i=0;i<=l;i++){
        printf("%c",a[i]);
    }*/
    for(int k=0;k<=25;k++){
        memset(tong,0,sizeof(tong));
        int sum=0;
        for(int i=0;i<=l;i++){
            int q;
            if(a[i]>='a'&&a[i]<='z'){
                q=a[i]-'a';
                q=(q+k)%26;
                tong[q]++;
                sum++;
            }else if(a[i]>='A'&&a[i]<='Z'){
                q=a[i]-'A';
                q=(q+k)%26;
                tong[q]++;
                sum++;
            }
        }
        for(int i=0;i<=25;i++){
            tp[i]=double(tong[i])/double(sum);
        }
        suan(k);
    }
    for(int i=0;i<=l;i++){
        if(a[i]>='a'&&a[i]<='z'){
            int q=a[i]-'a';
            printf("%c",(q+zuik)%26+'a');
        }else if(a[i]>='A'&&a[i]<='Z'){
            int q=a[i]-'A';
            printf("%c",(q+zuik)%26+'A');
        }else printf("%c",a[i]);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章