poj 1026 Cipher 置换群
对于每个 Block 求出其 循环因子,我这里是用 Vector 动态数组,省事
循环因子顾名思义就是置换会出现循环. 这样把时间复杂度降下来.
因为串总长才 200 , 分别处理每一个循环因子. 可以选择一个一个移动模拟, 也可以一次到位. 我都试了下,都是700+Ms.
虽然区别不大, 估计是数据问题吧. 数据量大了肯定影响很大.
View Code
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<algorithm> #include<iostream> #include<vector> using namespace std; vector<int> Q[220]; int a[220], n, num; bool vis[220]; int check( int s ) { for(int i = s; i <= n; i++) if( !vis[i] ) return i; return -1; } void init() { num = 0; for(int i = 0; i <= n; i++) Q[i].clear(); memset( vis, 0, sizeof(vis) ); int pos = 1; while( ( pos = check(pos) ) != -1 ) { int s = pos; while( !vis[s] ) { vis[s] = true; Q[num].push_back(s); s = a[s]; } num++; pos++; } /* //test OutPut // for(int i = 0; i < num; i++) // { // // printf("("); // for(int j = 0; j < Q[i].size(); j++) // printf( j == 0 ? "%d" : ",%d", Q[i][j] ); // printf(")"); // } // puts(""); // */ } int main() { while( scanf("%d", &n) , n ) { for(int i = 1; i <= n; i++) scanf("%d", &a[i]); init(); int k; char str[220], tmp[220]; while( scanf("%d%*c", &k), k ) { gets(str+1); int len = strlen( str+1 ); for(int i = len+1; i <= n; i++) str[i] = ' '; // for(int i = 1; i <= n; i++) // printf("%c", str[i]); puts(""); for(int i = 0; i < num; i++) { int tot = Q[i].size(); if( tot <= 1 ) continue; //一次移动多个 int t = k%tot; for(int j = tot-t; j < tot; j++) tmp[ Q[i][j] ] = str[ Q[i][j] ]; for(int j = tot-t-1; j >= 0; j--) str[ Q[i][j+t] ] = str[ Q[i][j] ]; for(int j = tot-t; j < tot; j++) str[ Q[i][ j-(tot-t)] ] = tmp[ Q[i][j] ]; // 一次移动一个 /*for(int j = 1; j <= (k%tot); j++) { char ch = str[ Q[i][tot-1] ]; for( int x = tot-1; x > 0; x--) str[ Q[i][x] ] = str[ Q[i][x-1] ]; str[ Q[i][0] ] = ch; }*/ } for(int i = 1; i <= n; i++) printf("%c", str[i] ); printf("\n"); } printf("\n"); } return 0; }