Hduoj1439【加密】

</pre><pre name="code" class="cpp">/*Cipher 
Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 0   Accepted Submission(s) : 0
Font: Times New Roman | Verdana | Georgia 
Font Size: ← →
Problem Description
Bob and Alice started to use a brand-new encoding scheme. Surprisingly it is not a Public Key Cryptosystem, but their encoding and decoding 
is based on secret keys. They chose the secret key at their last meeting in Philadelphia on February 16th, 1996. They chose as a secret key 
a sequence of n distinct integers, a1 ; . . .; an, greater than zero and less or equal to n. The encoding is based on the following principle. 
The message is written down below the key, so that characters in the message and numbers in the key are correspondingly aligned. Character in 
the message at the position i is written in the encoded message at the position ai, where ai is the corresponding number in the key. And then 
the encoded message is encoded in the same way. This process is repeated k times. After kth encoding they exchange their message.

The length of the message is always less or equal than n. If the message is shorter than n, then spaces are added to the end of the message 
to get the message with the length n.

Help Alice and Bob and write program which reads the key and then a sequence of pairs consisting of k and message to be encoded k times and 
produces a list of encoded messages. 

Input
The input file consists of several blocks. Each block has a number 0 < n <= 200 in the first line. The next line contains a sequence of n 
numbers pairwise distinct and each greater than zero and less or equal than n. Next lines contain integer number k and one message of ascii 
characters separated by one space. The lines are ended with eol, this eol does not belong to the message. The block ends with the separate 
line with the number 0. After the last block there is in separate line the number 0. 

Output
Output is divided into blocks corresponding to the input blocks. Each block contains the encoded input messages in the same order as in input 
file. Each encoded message in the output file has the lenght n. After each block there is one empty line. 
Sample Input
10
4 5 3 7 2 8 1 6 10 9
1 Hello Bob
1995 CERC
0
0

Sample Output
BolHeol b
C RCE

Source
ACM暑期集训队练习赛(5) 
*/
/* 
#include<stdio.h>
#include<string.h>
int map[210], f[210];
char s[210];
int find(int x)
{
	if(x != f[x])
	f[x] = find(f[x]);
	return f[x];
}
void merge(int x, int y)
{
	x = find(x);
	y = find(y);
	if(x != y)
	{
		f[x] = y;
	}
}
int gcd(int x, int y)
{
	if(!y)
	return x;
	else 
	return (y, x%y);
}
int main()
{
	int n, i, j, k, m;
	while(scanf("%d", &n) != EOF && n)
	{
		for(i = 1; i <= n; ++i)
			f[i] = i;
		for(i = 1; i <= n; ++i)
		{
			scanf("%d", &map[i]);
			merge(i, map[i]);
		}
		int cy = 1;
		for(i = 1; i <= n; ++i)
		{
			if(f[i])
			{
				k = 1;
				for(j = i+1; j <= n;++j)
				{
					if(f[j] == f[i])
					{
						f[j] = 0;
						++k;
					}
				}
				if(cy % k != 0)
				cy = cy * k / gcd(cy,k);
			}
		}
		int l;
		while(scanf("%d", &m) != EOF)
		{
			if(m)
			{
				gets(s);
				l = strlen(s);
				if(l < n+1)
				{
					for(i = l; i <= n; ++i)
					s[i] = ' ';
					s[i] = '\0';
				}
				m %= cy;
				char s1[210];
				while(m--)
				{
					for(i = 1; i <= n; ++i)
					s1[map[i]] = s[i];
					for(i = 1; i <= n; ++i)
					s[i] = s1[i];
				}
				for(i = 1; i <= n; ++i)
				printf("%c", s[i]);
				printf("\n");
			}
			else
			break;
		}
		printf("\n");
	}
	return 0;
}
TLE*/

#include<stdio.h>
#include<string.h>
int map[210];
char s[210], s1[210];
int main()
{
	int i, j, k, n;
	while(scanf("%d", &n) != EOF && n)
	{
		for(i = 1; i <= n; ++i)
			scanf("%d", &map[i]);
		int r[210], a[210];
		memset(r, 0, sizeof(r));
		for(i = 1; i <= n; ++i)
		{
			if(!r[i])
			{
				int temp = map[i];
				j = 1;
				a[j] = temp;
				while(temp != i)//一边找循环周期一边记录同周期的数 
				{
					temp = map[temp];
					a[++j] = temp;
				}
				for(int l = 1; l <= j; ++l)//记录周期 
					r[a[l]] = j;
			}
		}
		
		while(scanf("%d", &k) != EOF && k)
		{
			gets(s);
			int len = strlen(s);
			while(len < n+1)
			s[len++] = ' ';
			s[len] = '\0';
			for( i = 1; i <= n; ++i)//对每一个字母进行置换 
			{
				int t = k%r[i];
				if(t)
				{
					--t;
					j = map[i];
					while(t--)
					{
						j = map[j];
					}
					s1[j] = s[i];
				}
				else
				s1[i] = s[i];
			}
			for(i = 1; i <= n; ++i)
			printf("%c", s1[i]);
			printf("\n");
		}
		printf("\n");
	} 
	return 0;
} 

题意:给出一个数n,并且给出n个数,和一个字符串,将第i个字符换到第i个数所示的位置,每一个字符都进行一次这样的操作称为一次置换,同时给出一个k,表示置换k次,求置换k次后的字符串。注意(输入的字符串长度有可能长度不够n,则在字符串尾不上空格直至长度为n)。

思路:从输入输出可以明显看出,对于每几个字符之间都有一个置换周期,每置换一定次数这几个字符都会回到原位,所以我们可以求出每一位的置换周期,然后对于输入的k次置换就可以进行取余大大的简化置换次数。求周期思路很简单,就是对于一个字符进行置换模拟,多少次后回到原位,将次数就作为当前字符的周期,其次就是可以顺便记录下置换过程中所经过的位置,对于经过的位置来说周期是一样的,节省时间。求出周期后进是对每一位进行取余置换了。

难点:难点就在于想到求每一位的周期,起初我是求得整个字符串的周期,然后进行取余置换的,结果超时了,因为对于每一个字符来说,整个字符串的周期必定是它自身的周期的倍数,所以对于很多字符来说进行了很多次重复的置换。

你可能感兴趣的:(Hduoj1439【加密】)