poj1026 Cipher

题目意思可概括为给定集合S = {1,..,n}的一个双射关系f, 求经过k次复合之后元素i对应的元素fk(i) (i∈S)。

由于函数是双射,一个原像对应唯一一个像,同样一个像有唯一一个原像,考虑整个映射关系,存在整数m∈ Z,使得fm=f0=I。

即具有周期性。

每个元素映射回它自己有独立的周期T(i),整个映射的周期T=lcm(T(i)), i ∈ S。

独立处理更快,但对于本题也是刚刚卡过。

当然如果事先把所有询问读入加以预处理或者直接全部预处理会更快。

样例代码860ms卡过。

http://poj.org/problem?id=1026
 
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 const int maxn = 200 + 10;
 8 int n;
 9 char s[maxn];
10 int f[maxn];
11 int period[maxn];
12 int repeats;
13 
14 struct Node{
15     int from, to;
16 }node[maxn];
17 
18 int gcd(int a, int b){
19     if(!b) return a;
20     return gcd(b, a % b);
21 }
22 
23 bool cmp(Node a, Node b){
24     return a.to < b.to;
25 }
26 
27 void init(){
28     for(int i = 0; i < n; i++){
29         int t = f[i], cnt = 1;
30         while(i != t) t = f[t], ++cnt;
31         period[i] = cnt;
32     }
33 }
34 
35 void solve(){
36     for(int i = 0; i < n; i++) node[i].from = node[i].to = i;
37     for(int i = 0; i < n; i++){
38         int p1 = repeats % period[i];
39         while(p1--) node[i].to = f[node[i].to];
40     }
41     sort(node, node + n, cmp);
42     for(int i = 0; i < n; i++) printf("%c", s[node[i].from]);
43     printf("
");
44 }
45 
46 int main(){
47     while(~scanf("%d", &n) && n){
48         for(int i = 0, j; i < n; i++){
49             scanf("%d", &j);
50             f[i] = j - 1;
51         }
52         init();
53         while(~scanf("%d", &repeats) && repeats){
54             getchar();
55             gets(s);
56             int len = strlen(s);
57             for(int i = len; i < n; i++) s[i] = ' ';
58             s[n] = '';
59             solve();
60         }
61         printf("
");
62     }
63     return 0;
64 }
View Code
原文地址:https://www.cnblogs.com/astoninfer/p/4737986.html