题目链接:点击打开链接
题目大意:给出一个编码的顺序,每经过一次编码第i位上的字符回到第a[i]位上。然后给出一个k,和初始的串,问编码k次后的串是什么。
k可能会很大,不能暴力,所以要用置换群,找出轮换的环,假设环中有m个数,那么每编码m次,就代表这又回到了初始状态,可以用k%m,这样减少编码的次数。如果在记录轮换的位置,那么对于轮换中的第i个字符编码k次,就变成了轮换中的第(i+k)%m个字符。这样直接可以计算出最终的结果。
注意,题目不难,但是输入让人头疼,,,,经过多次wa,测试出只有(getline除外):
gets(str) ;
int len = strlen(str) ;
for(i = len ; i <= n ; i++)
str[i] = ‘ ‘ ;
而且一定要有后面的for,不然就错误,,,,,
#include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std ; char str[210] , s[210] , ch ; int cnt ; int a[210] , vis[210] ; vector <int> vec[210] ; int vec_num ; void grop(int n) { int i , j ; vec_num = 0 ; memset(vis,0,sizeof(vis)) ; for(i = 1 ; i <= n ; i++) { if( vis[ a[i] ] ) continue ; j = i ; while( !vis[ a[j] ] ) { vis[ a[j] ] = 1 ; vec[ vec_num ].push_back( j ) ; j = a[j] ; } vec_num++ ; } } int main() { int n , m , k , i , j , l , num , mod , temp ; while( scanf("%d", &n) && n ) { for(i = 1 ; i <= n ; i++) { scanf("%d", &a[i]) ; } for(i = 0 ; i < n ; i++) vec[i].clear() ; grop(n) ; while( scanf("%d", &k) && k ) { cnt = 0 ; memset(s,0,sizeof(s)) ; memset(str,0,sizeof(str)) ; /*getchar() ; while( ch = getchar() ) { if( ch == '\n' ) break ; str[++cnt] = ch ; }*/ gets(str) ; int len = strlen(str) ; for(i = len ; i <= n ; i++) str[i] = ' ' ; for(i = 0 ; i < vec_num ; i++) { num = vec[i].size() ; for(j = 0 ; j < num ; j++) { l = (j+k)%num ; s[ vec[i][l] ] = str[ vec[i][j] ] ; } } for(i = 1 ; i <= n ; i++) { printf("%c", s[i]) ; } printf("\n") ; } printf("\n") ; } return 0 ; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-01 23:59:45