poj 1026 Cipher (置换群,循环节)
题意:
Bob and Alice started to use a brand-new encoding scheme. Surprisingly it is not a Public Key Cryptosystem, but their encoding and decoding is based on secret keys. They chose the secret key at their last meeting in Philadelphia on February 16th, 1996. They chose as a secret key a sequence of n distinct integers, a1 ; . . .; an, greater than zero and less or equal to n. The encoding is based on the following principle. The message is written down below the key, so that characters in the message and numbers in the key are correspondingly aligned. Character in the message at the position i is written in the encoded message at the position ai, where ai is the corresponding number in the key. And then the encoded message is encoded in the same way. This process is repeated k times. After kth encoding they exchange their message.
The length of the message is always less or equal than n. If the message is shorter than n, then spaces are added to the end of the message to get the message with the length n.
Help Alice and Bob and write program which reads the key and then a sequence of pairs consisting of k and message to be encoded k times and produces a list of encoded messages.
思路:
把置换群的多组循环节找出来,对于给定的字符串,和置换次数(mathit k),对每个循环节分开处理,置换次数可以对循环节长度取模。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
// #include <bits/stdc++.h>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), ' ', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define chu(x) if(DEBUG_Switch) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
ll poww(ll a, ll b) { if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a ;} a = a * a ; b >>= 1;} return ans;}
inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') fh = -1; c = getchar();} while (c >= '0' && c <= '9') tmp = tmp * 10 + c - 48, c = getchar(); return tmp * fh;}
void pvarr_int(int *arr, int n, int strat = 1) {if (strat == 0) {n--;} repd(i, strat, n) {printf("%d%c", arr[i], i == n ? '
' : ' ');}}
void pvarr_LL(ll *arr, int n, int strat = 1) {if (strat == 0) {n--;} repd(i, strat, n) {printf("%lld%c", arr[i], i == n ? '
' : ' ');}}
const int maxn = 1010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
#define DEBUG_Switch 0
int n;
int a[maxn];
char t[maxn];
char s[maxn];
int cnt;
int vis[maxn];
std::vector<int> v[maxn];
void find_loop()
{
cnt = 0;
repd(i, 0, n)
{
vis[i] = 0;
v[i].clear();
}
int tot = 0;
repd(i, 0, n-1)
{
if (vis[i] == 0)
{
cnt++;
int id = i;
while (vis[id] == 0)
{
v[cnt].pb(id);
vis[id] = ++tot;
id = a[id];
}
}
}
}
void solve(int len, int k)
{
strcpy(t, s);
repd(i, 1, cnt)
{
int num = sz(v[i]);
int x = k % num;
for (int j = 0; j < num; ++j)
{
// cout<<v[i][j]<<" "<<v[i][(j - x + num) % num]<<endl;
s[v[i][j]] = t[v[i][(j - x + num) % num]];
}
}
}
int main()
{
#if DEBUG_Switch
freopen("C:\code\input.txt", "r", stdin);
#endif
//freopen("C:\code\output.txt","w",stdout);
while (~scanf("%d", &n) && n)
{
repd(i, 0, n - 1)
{
a[i] = readint();
a[i]--;
}
find_loop();
int len;
int k;
while (~scanf("%d", &k) && k)
{
getchar();
gets(s);
len = strlen(s);
while (len < n)
{
s[len++] = ' ';
}
s[len]=' ';
solve(len, k);
printf("%s
", s );
// memset(s, ' ', sizeof(s));
}
printf("
");
}
return 0;
}