链接:https://ac.nowcoder.com/acm/contest/6777/B
来源:牛客网
题目描述
牛牛想给牛妹写信,但是牛牛怕信中的信息泄露出去,于是用playfair加密信息。加密过程中的j都由i来代替。playfair加密算法首先需要绘制密码表,密码表是一个5*5的矩阵,开始由密钥按顺序排列,其余按照未出现的字母顺序。若密钥中含有重复字母需要将重复字母去掉,若有j用i来代替,例如密钥为nowcoder,得到的密码表为
加密明文需要符合以下规则:
将明文中每两个字母组成一对,若成对后是两个相同字母或留下一个字母无法成对,则不进行变化直接放入密文中
明文对p1p2在同一行,对应密文对c1c2分别为紧靠p1p2右端的字母,最后一列右端对应第一列。例如明文对为rf,对应密文对为ae
明文对p1p2在同一列,对应密文对c1c2分别为紧靠p1p2下方的字母,最后一行下方对应第一行。例如明文对为rv,对应密文对为ho
明文对p1p2不在同一行且不在同一列,对应密文对c1c2分别为p1p2确定的矩形中的同行另外两角,例如明文对为hb,对应密文对为kr
现在牛牛告诉你密钥和明文你能告诉牛牛密文是什么吗?
示例1
输入
复制
“nowcoder”,“iloveyou”
输出
复制
“kgrobunv”
备注:
1\leq|key|\leq 261≤∣key∣≤26,1\leq |str|\leq 10^31≤∣str∣≤10
3
,输入保证都为小写字母
class Solution {
public:
char mib[5][5] = { 0 };//加密表
int pc[300] = { 0 };//桶去重
string zmb = "abcdefghijklmnopqrstuvwxyz";//预处理字母表
string Encode(string key, string str) {
string zzw;
for (int i = 0; i < key.length(); i++)//桶去重 并形成加密表的串
{
if (pc[key[i]] == 0) {
if (key[i] == 'j' || key[i] == 'i')//替换j和i
{
pc['j'] = 1;
pc['i'] = 1;
zzw += 'i';
}
else
{
zzw += key[i];
pc[key[i]] = 1;
}
}
}
for (int i = 0; i < zmb.length(); i++)//桶去重 并形成加密表的串
{
if (pc[zmb[i]] == 0) {
if (zmb[i] == 'j')//j不要 也不替换i一定会出现一次
{
continue;
}
else
{
zzw += zmb[i];
pc[zmb[i]] = 1;
}
}
}
int k = 0, mp = 0;
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)//预处理加密表
{
mib[i][j] = zzw[k++];
}
}
for (int i = 0; i < str.length(); i++)//原文j替换为j
{
if (str[i] == 'j')str[i] = 'i';
}
string mw;
for (int i = 0; i < str.length() - str.length() % 2; i += 2)//让i只会到偶数停下 奇数的话 下面有处理
{
int zbx = 0, zby = 0, zbx1 = 0, zby1 = 0;
for (int iq = 0; iq < 5; iq++)//查找加密表坐标
{
for (int jq = 0; jq < 5; jq++)
{
if (mib[iq][jq] == str[i])
{
zbx = iq;
zby = jq;
}
}
}
for (int iq = 0; iq < 5; iq++)//查找加密表坐标
{
for (int jq = 0; jq < 5; jq++)
{
if (mib[iq][jq] == str[i + 1])
{
zbx1 = iq,
zby1 = jq;
}
}
}
if (str[i] == str[i + 1])
{
mw += str[i];
mw += str[i + 1];
}
else if (zbx == zbx1 && zby != zby1)
{
mw += mib[zbx][(zby + 1) % 5];
mw += mib[zbx1][(zby1 + 1) % 5];
}
else if (zbx != zbx1 && zby == zby1)
{
mw += mib[(zbx + 1) % 5][zby];
mw += mib[(zbx1 + 1) % 5][zby1];
}
else if (zbx != zbx1 && zby != zby1)
{
mw += mib[zbx][zby1];
mw += mib[zbx1][zby];
}
}
if (str.length() % 2 == 1)//处理多一个字母的情况
{
mw += str[str.length() - 1];
}
return mw;
}
};
链接:https://ac.nowcoder.com/acm/contest/6777/C
来源:牛客网
题目描述
牛牛非常擅长摇骰子,不管给他一个什么样的骰子他都能准确的掷出他想要的那一面。现在有一个四面体骰子,四个面分别是四个整数0,3,7,11。牛牛在玩一个游戏。牛牛初始在一个数轴的原点,每当他摇出一个数字x,他可以自行选择向左走x步或者向右走x步。牛牛想知道他最少摇多少次骰子可以从原点到达坐标为p的点。
现在一共有N次询问,请你返回从0点到询问的每一个坐标arr[i]所需要摇筛子的最小次数。
示例1
输入
复制
[1,4,14]
输出
复制
[3,2,2]
说明
从0到1最少需要摇3次骰子(0->7->4->1)(走法不唯一,比如0->11->4->1也只需要掷3次骰子)
从0到4最少需要摇2次骰子(0->7->4)
从0到14最少需要摇2次骰子(0->7->14)
示例2
输入
复制
[6,25]
输出
复制
[2,3]
说明
从0到6最少需要摇2次骰子(0->3->6)
从0到25最少需要摇3次骰子(0->7->18->25)
备注:
对于20%的数据1\leq N\leq 5,1\leq arr[i]\leq 1e51≤N≤5,1≤arr[i]≤1e5
对于50%的数据1\leq N\leq 1e5,1\leq arr[i]\leq 5e51≤N≤1e5,1≤arr[i]≤5e5
对于100%的数据1\leq N\leq 1e5,1\leq arr[i]\leq 1e91≤N≤1e5,1≤arr[i]≤1e9
class Solution {
public:
/**
* 把所有询问的答案按询问顺序放入vector里
* @param arr int整型vector 要查询坐标的数组
* @return int整型vector
*/
int v[1005];
int a[5]={0,3,7,11};
typedef long long ll;
typedef pair<ll,ll>pll;
vector<int> MinimumTimes(vector<int>& arr) {
// write code here
queue<pll>q;
q.push(pll(0,0));
v[0]=0;
while(!q.empty()){
pll no=q.front();
q.pop();
for(int i=0;i<4;i++){
for(int j=-1;j<2;j+=2){
int x=no.first+a[i]*j;
if(x>=1&&x<=1000){
if(!v[x]){
v[x]=no.second+1;
q.push({x,v[x]});
}
}
}
}
}
vector<int>res;
for(auto i:arr){
if(i>22){
res.push_back((i-11)/11+v[i%11+11]);
}
else res.push_back(v[i]);
}
return res;
}
};