poj1026--Cipher(置换群)
2015-07-25 10:45
399 查看
题目链接:点击打开链接
题目大意:给出一个编码的顺序,每经过一次编码第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 ;
}
题目大意:给出一个编码的顺序,每经过一次编码第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 ;
}
相关文章推荐
- vc6.0在win8或8.1下“打开文件”功能不用用的解决办法
- selenium自动化测试(一)
- UVa 1394 - And Then There Was One(约瑟夫数论)
- Thieves (hdu 3491 拆点 最小割)
- adb调试(1)--权限与管理
- 万网企业邮箱拒信常规问题对照表
- PS 滤镜— —Marble 效果
- adb devices no permissions 解决办法
- 让ProgressDialog在setCancelable(false)时按返回键可dismiss
- POJ-3273 Monthly Expense
- 由前序(后序)中序构造二叉树
- 介紹好用工具:RichCopy (檔案複製與備份的絕佳工具)
- ISA2006如何用SQL来记录日志?
- 17. JavaScript Math(算数)对象
- Android WebView 开发详解(一)
- [Leetcode 151, Medium] Reverse Words in a String
- opencv+pcl配置
- 10570 - Meeting with Al (贪心)
- 列出文件夹下所有文件夹的树形结构--Dos命令 tree的使用
- JavaScript权威指南_139_第15章_脚本化文档_15.9-HTML表单-选取表单和表单元素