2019.2.15小白之路:百练2818-密码

总时间限制: 1000ms 内存限制: 65536kB
描述

Bob 和 Alice 开始使用一种全新的编码系统。它是一种基于一组私有钥匙的。他们选择了n个不同的数a1 , . . .,an,它们都大于0小于等于n。 机密过程如下:待加密的信息放置在这组加密钥匙下,信息中的字符和密钥中的数字一一对应起来。信息中位于i位置的字母将被写到加密信息的第ai个位置,ai 是位于i位置的密钥。加密信息如此反复加密,一共加密 k 次。 信息长度小于等于n。如果信息比 n 短, 后面的位置用空格填补直到信息长度为n。 请你帮助 Alice 和 Bob 写一个程序,读入密钥,然后读入加密次数 k 和要加密的信息,按加密规则将信息加密。

输入

输入包括几块。每块第一行有一个数字n, 0 < n <= 200.接下来的行包含n个不同的数字。数字都是大于0小于等于n的。下面每行包含一个k和一个信息字符串,它们之间用空格格开。每行以换行符结束,换行符不是要加密的信息。每个块的最后一行只有一个0。 最后一个块后有一行,该行只有一个0。

输出

输出有多个块,每个块对应一个输入块。每个块包含输入中的信息经过加密后的字符串,顺序与输入顺序相同。所有加密后的字符串的长度都是 n。每一个块后有一个空行。

样例输入

10
4 5 3 7 2 8 1 6 10 9
1 Hello Bob
1995 CERC
0
0

样例输出

BolHeol  b
C RCE

这道题真的……一直超时一直超时一直超时,写的心力交瘁。
暴力解决会超时!
最后(在大佬的指导下),利用变换是固定周期的,只在固定数量的位置间变化的规律(比如1到3再到7后又会回到1,固定数量为3,就是周期为3)所以就用count数组储存这个周期,比如count[1],count[3],count[7]都存3,然后变换的时候只需要变换k%count[i]次就行,这样就可以大大减少运算。

代码段

#include <string>
#include <iostream>

using namespace std;

void preprocess(int *key, int n, int *count)
{
	for (int index = 1; index <= n; index++) {
		int begin = index;
		int next = begin;
		int num = 1;
		while (key[next] != begin) {
			num++;
			next = key[next];
		}
		count[index] = num;
	}
}

int main() {
	int key[201];
	int final_position[201];
	int count[201];
	int n;
	cin >> n;
	while (n != 0) {
		for (int i = 1; i <= n; i++) 
			cin >> key[i];
		preprocess(key, n, count);
		int k;
		cin >> k;
		while (k != 0) {
			string s;
			getline(cin, s);
			for (int index = 1; index <= n; index++) {
				int Final = index;
				int num = k % count[index];
				for (int i = 0; i < num; i++) 
					Final = key[Final];
				final_position[Final] = index;
			}
			int length = s.length();
			for (int i = 1; i <= n; i++) {
				if (final_position[i] > length - 1) 
					cout << ' ';
				else 
					cout << s[final_position[i]];
			}
			cout << endl;
			cin >> k;
			if (k == 0) 
				cout << endl;
		}
		cin >> n;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/shensen0304/article/details/87359341
今日推荐