密码学(模拟)

链接:https://ac.nowcoder.com/acm/contest/3979/B
来源:牛客网

题目描述
考虑一种加密方式,它需要一个任意长度的原文 {m}m 和秘钥 {key}key,其中要求原文和秘钥只包含大写和小写的英文字符。
首先定义字符之间的加密,用字符 {a}a 去加密字符 {b}b 的结果是:
首先把 {a}a 和 {b}b 转成数字 {x}x 和 {y}y。转换的规则是,小写字母 {a}a 到 {z}z 依次对应 {0}0 到 {25}25,大写字母依次对应 {26}26 到 {51}51。
计算 {x}x 和 {y}y 的和 {z}z,对 {52}52 取模,即计算 (x+y) \bmod 52(x+y)mod52。
返回数字 {z}z 对应的字符。
现在来讲如何用秘钥 {key}key 来加密原文 {m}m:
如果秘钥的 {key}key 的长度小于 {m}m,那么不停重复 {key}key 直到长度不小于 {m}m 为止。举例来说,如果原文是 {beijing}beijing,秘钥是 {PKUSAA}PKUSAA,那么秘钥需要被重复称 {PKUSAAPKUSAA}PKUSAAPKUSAA。
假设原文的长度是 {n}n,那么对于每一个 {[1,n]}[1,n] 的数字 {i}i,都用 {key}key 的第 {i}i 个字符去加密 {m}m 的第 {i}i 个字符。
返回结果。
那么用 {PKUSAA}PKUSAA 去加密 {beijing}beijing 的结果就是:{QOcbINV}QOcbINV。
现在火山哥有 {n}n 个字符串,s_1 到 s_n
他对这些字符串做了 {m}m 次加密操作:第 {i}i 次加密操作用第 s_{​x_i} 去加密 s_{​y_i} ,并把 s_{​yi}
替换成加密结果。
现在依次给出 {m}m 次加密操作,以及加密操作结束后每一个字符串的模样,你可以还原出这 {n}n 个字符串原来的模样吗?
输入描述:
第一行输入两个整数 {n},{m}n,m (1\leq n,m\leq 1000)(1≤n,m≤1000)。
接下来 {m}m 行每行输入两个整数 x_i,y_i,表示依次加密操作,保证 x_ 不等于 y_i。
接下来 {n}n 行每行输入一个字符串,表示加密最后的结果。字符串的长度在 {1}1 到 {100}100 之间,只包含大小写英文字符。
输出描述:
输出 {n}n 行,每行一个字符串,表示原本的字符串。
示例1
输入

2 1
1 2
PKUSAA
QOcbINV
输出

PKUSAA
beijing

思路:这题也是一道签到题,只需要把解密模拟出来就可以了,只是过程可能有点麻烦。

#include<bits/stdc++.h>
using namespace std;
 
int main()
{
    int n,m;
    cin>>n>>m;
    int a[m+10],b[m+10];
    for(int i=1; i<=m; i++)
    {
        cin>>a[i]>>b[i];
    }
    string t[n+10];
    for(int i=1; i<=n; i++)
    {
        cin>>t[i];
    }
    int xi,yi;
    for(int i=m; i>0; i--)
    {
        xi=a[i];
        yi=b[i];
        int len1 = t[xi].length();
        int len2 = t[yi].length();
        int z=0,x=0,y=0;
        for(int j=0; j<len2; j++)
        {
            if(t[yi][j]>='a'&&t[yi][j]<='z')
                z=t[yi][j]-'a';
            else
                z=t[yi][j]+26-'A';
            if(t[xi][j%len1]>='a'&&t[xi][j%len1]<='z')
                  x=t[xi][j%len1]-'a';
                  else
                    x=t[xi][j%len1]-'A'+26;
            y=(z-x+52)%52;
            if(y<26)
                t[yi][j]=y+'a';
            else
                t[yi][j]=y+'A'-26;
        }
    }
    for(int i=1; i<=n; i++)
        cout<<t[i]<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值