分析:
key:
4 5 3 7 2 8 1 6 10 9(转换为数组的下标为:3 5 2 6 1 7 0 6 9 8)
消息长度也为10,下标为
0 1 2 3 4 5 6 7 8 9
其实就是消息的下标按照key来置换,当经过若干次交换之后又会回到原来的位置,姑且称这个交换的次数为循环长度loopLen
例如:0->3->6->0,那么0号位置的消息字符的循环长度loopLen[0] = 3
1->4->1,那么1号位置的消息字符的循环长度loopLen[1] = 2
这样,我们算出每个位置的循环长度,在需要进行k次加密的时候,只需要交换该位置i上的字符k%loopLen[i]次就可以得到最终该位置上应该有的字符。
//Problem: 1026 //Memory: 496K Time: 172MS //Language: C++ Result: Accepted #include <stdlib.h> #include <iostream> #include <string> #include <vector> using namespace std; typedef struct _MSG { unsigned k; string msg; }MSG; int main() { unsigned i; unsigned n,lastN; char eol; vector<unsigned> key; vector<MSG> msgs; MSG m; string mm; while(true) { cin>>n; if(n==0) { n = lastN; break; } lastN = n; for(i=0;i<n;i++) { unsigned temp; cin>>temp; key.push_back(temp-1); } getline(cin,mm);//输完key之后会输入一个换行符,用mm来接收,否则下面的getline将接收这个换行符并结束 while(true) { getline(cin,mm,'\n');//eol就是‘\n' if(mm[0] == '0') break; string s=""; for(i=0;i<mm.size();i++) { if(mm[i]!=' ') s += mm[i]; else break; } m.k = atoi(s.c_str()); m.msg = mm.substr(i+1,mm.size()-i); for(i=m.msg.size(); i<n; i++)//如果消息的长度小于n,则用' '填充 m.msg.push_back(' '); msgs.push_back(m); } vector<unsigned> loopLen(n,0); for(i=0; i<n; i++) { unsigned j = key[i]; unsigned count = 1; while(i!=j) { j = key[j]; count++; } loopLen[i] = count;//对于key中的每一个数i,交换loopLen[i]次之后又会恢复到原始值如:0-3-6-0,loopLen[0]=3,1-4-1,loopLen[1]=2 } vector<string> encodedMsg; for(vector<MSG>::iterator it=msgs.begin();it!=msgs.end();it++) { unsigned pos; string s1(it->msg); for(int j=0; j<n; j++) { pos = j; for(i=0; i<(it->k)%loopLen[j]; i++) { pos = key[pos]; } s1[pos] = it->msg[j]; } encodedMsg.push_back(s1); } for(vector<string>::iterator it=encodedMsg.begin();it!=encodedMsg.end();it++) cout<<*it<<endl; cout<<endl; key.clear(); msgs.clear(); encodedMsg.clear(); } return 0; }

276

被折叠的 条评论
为什么被折叠?



