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.
- 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).
- Repeat the following step m times.
- 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;
}