TZOJ:1009: 目标柏林

本文讲述了二战期间苏军面临的解密任务,德军使用的一种基于字符旋转的加密方法。文章详细描述了加密过程并提供了一个C++程序来还原原文。
摘要由CSDN通过智能技术生成

标签:字符串

描述

1945年初,苏军和英美联军已从东西两面攻入德国国境。
4月初,在苏军和英美联军的夹击下,德军只能龟缩在以柏林为中心的德国东部的狭长地带,成了瓮中之鳖。
但希特勒困兽犹斗,一方面发出摧毁一切设施,实行“焦土”政策的指令;
另一方面下令把德国分为南北两个行政区,各自作战,他自己则固守柏林。
在这一天,苏军结果一份传自柏林的加密电文。经初步破译,显示希特勒要调集100万兵力,
在柏林周围筑起了三层防卫圈,并集中3300架飞机,1500多辆坦克,1万门火炮和迫击炮,准备死守柏林。
形势很危机,我们需要马上破译所有密码。请你来遍个程序帮忙破译。

苏军知道德军用的加密方法是这样的:
1.获得一段文字后,求出它的长度(包括空格)len。
2.进入加密运算的第1步:把所有下标是1倍数的字符做顺时针旋转。
3.进入加密运算的第2步:把所有下标是2倍数的字符做逆时针旋转。
4.进入加密运算的第3步:把所有下标是3倍数的字符做顺时针旋转。
5.按上面的规则,第奇数步按顺时针旋转,偶数步按逆时针旋转,一直到第len步为止。

比如原文是:abcde
1.获得长度len = 5
2.1的倍数有1、2、3、4、5,所以把这5个字符按顺时针旋转,得到eabcd。
3.2的倍数有2、4,所以把这2个字符按逆时针旋转,得到ecbad。
4.3的倍数有3,所以把这1个字符按顺时针旋转,得到ecbad。
5.4的倍数有4,所以把这1个字符按逆时针旋转,得到ecbad。
6.5的倍数有5,所以把这1个字符按顺时针旋转,得到ecbad。
最后的结果是ecbad。

现在给你加密后的文章,让你还原成原来的文章。

输入

输入一篇加密后的文章,每行为一段。每段不超过1000个字符。
输入以文件结束(EOF)为止。

输出

输出解密后的文章。
每段一行。

样例输入

ecbad

样例输出

abcde

提示

C and C++ language can use :
char input[1001];
while(gets(input))
{
...
}

以下是AC代码:

/*
       1 2 3 4 5
    -> 5 1 2 3 4 [偶] 取5 , 1 2 3 4向右移 , 补上5
    -> 2 3 4 5 1 [奇] 取1 , 2 3 4 5向左移 , 补上1
*/

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 1010;

int main()
{
    char s[N] = {" "}; // 字符串
    while(gets(s + 1) != NULL) // 多样例读入
    {
        int len = strlen(s) - 1; // 求长度
        /*  
            i作为倍数
            只有一个数要转,不需要考虑,所以是len / 2
            同时是解密,所以倒着取
        */
        for (int i = len / 2; i > 0; i -- ) 
        {                                   
             if(i % 2 == 0) // 偶数情况
            {  
                int k = i * (len / i), j;   // k可以求出i倍数的最后一个
                char t = s[k];          // 从0开始,故减1
                for(j = k; j > i; j -= i)  // 开转
                {  
                    s[j] = s[j - i];  
                }  
                s[i] = t;  // 最后补
            } 
            else //与上同理
            {  
                int j , k = i * (len / i); 
                char t = s[i];  
                for(j = i; i + j <= k; j += i)  
                {  
                    s[j] = s[i + j];  
                }  
                s[k] = t;  
            }
            
            /* 检验输出 */
            /*for (int i = 0; i < len; i ++ ) cout << s[i];
            cout << endl;*/
            
        }
        
        /* 输出 */
        for (int i = 1; i <= len; i ++ ) cout << s[i];
        cout << endl;
    }
    
    return 0;
}
  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值