L-HDU 2371 Decode the Strings

L-HDU 2371 Decode the Strings

Problem Description
Bruce Force has had an interesting idea how to encode strings. The following is the description of how the encoding is done:

Let x 1,x 2,…,x n be the sequence of characters of the string to be encoded.

  1. Choose an integer m and n pairwise distinct numbers p 1,p 2,…,p n from the set {1, 2, …, n} (a permutation of the numbers 1 to n).
  2. Repeat the following step m times.
  3. For 1 ≤ i ≤ n set y i to x pi, and then for 1 ≤ i ≤ n replace x i by y i.

For example, when we want to encode the string “hello”, and we choose the value m = 3 and the permutation 2, 3, 1, 5, 4, the data would be encoded in 3 steps: “hello” -> “elhol” -> “lhelo” -> “helol”.

Bruce gives you the encoded strings, and the numbers m and p 1, …, p n used to encode these strings. He claims that because he used huge numbers m for encoding, you will need a lot of time to decode the strings. Can you disprove this claim by quickly decoding the strings?

Input
The input contains several test cases. Each test case starts with a line containing two numbers n and m (1 ≤ n ≤ 80, 1 ≤ m ≤ 10 9). The following line consists of n pairwise different numbers p 1,…,p n (1 ≤ p i ≤ n). The third line of each test case consists of exactly n characters, and represent the encoded string. The last test case is followed by a line containing two zeros.

Output
For each test case, print one line with the decoded string.
Sample Input

5 3
2 3 1 5 4
helol
16 804289384
13 10 2 7 8 1 16 12 15 6 5 14 3 4 11 9
scssoet tcaede n
8 12
5 3 4 2 1 8 6 7
encoded?
0 0
Sample Output

hello
second test case
encoded?

题意:给定一个数列,按照指定的移动方法移动 m 次后得到加密数列
p[1],p[2],p[3],p[4],p[5] => p[2],p[3],p[1],p[5],p[4]
求原数列

题解

相当于用单位矩阵通过特定变化实现交换

1 2 3 4 5 * 0 0 1 0 0=2 3 1 5 4
0 0 0 0 0 * 1 0 0 0 0=0 0 0 0 0
0 0 0 0 0 * 0 1 0 0 0=0 0 0 0 0
0 0 0 0 0 * 0 0 0 0 1=0 0 0 0 0
0 0 0 0 0 * 0 0 0 1 0=0 0 0 0 0
求逆矩阵,然后快速幂

复杂度

O(n3log m)== 80808032 < 1e7

算法

矩阵快速幂

代码

#include<bits\stdc++.h>
using namespace std; 
int n, m;
typedef struct node {
	int e[85][85];
	void init(){
		memset(e, 0, sizeof(e));
		for(int i = 0; i <= 85; i++) e[i][i] = 1;
	}
}Mat;

Mat ans, mp;

Mat Mut(Mat a, Mat b){
	Mat c;
	memset(c.e, 0, sizeof(c.e));
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n; j++){
			for(int k = 1; k <= n; k++){
				c.e[i][j] += a.e[i][k] * b.e[k][j];
			}
		}
	}
	return c;
}

Mat quick_mod(Mat a, int k) {
	Mat one;
	one.init();
	while(k){
		if(k&1) one = Mut(one, a);
		a = Mut(a, a);
		k >>= 1;
	}
	return one;
}

int main() {
	freopen("test.in", "r", stdin);
	while(cin >> n >> m && (n+m)!=0) {
		char s[100] = {};
		memset(ans.e, 0, sizeof(ans.e));
		memset(mp.e, 0, sizeof(mp.e));
		for(int i = 1; i <= n; i++) cin >> mp.e[1][i];
		for(int i = 1; i <= n; i++) ans.e[i][mp.e[1][i]] = 1;// 逆矩阵 

		getchar(); // 吃回车 
		gets(s+1);	
		
		ans = quick_mod(ans, m);
//		ans = Mut(mp, ans);
		for(int i = 1; i <= n; i++) 
			for(int j = 1; j <= n; j++)
				if(ans.e[i][j]){
					cout << s[j] ;
				}	
		cout << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值