NOIP2012提高组day1 vigenere密码 题解

样例1

样例输入1[复制]

CompleteVictory
Yvqgpxaimmklongnzfwpvxmniytm

样例输出1[复制]

Wherethereisawillthereisaway

限制

每个测试点1s忽略密钥的大小写,于是if ord(miyue) > 96 then miyue := chr(ord(miyue)-32)根据公式ord(mingwen) = ord(miwen) - ord(miyue) + 65推算出明文的代码然后检查与密文的大小写是否一致,不一致再+26即可

 

program  viengere;
var k,s,ans:ansistring;
    lenk,lens,num,i,sum:longint;
    down:array[1..1000] of boolean; //记录是否需要把该字符转回小写
begin
{assign(input,'vigenere.in');
reset(input);
assign(input,'vigenere.out');
rewrite(output);}readln(k); readln(s); lenk:=length(k); lens:=length(s); num:=0; sum:=0;
k:=upcase(k);
for i:=1 to lens do //是否是小写,同时转成大写方便计算,虽然麻烦,但数据只有1000,时间可不计
 if ord(s[i])>ord('Z') then
 begin
  down[i]:=true; s[i]:=chr(ord(s[i])-32);
 end;

for i:=1 to lens do //处理
begin
 inc(num); if num>lenk then num:=1;
 sum:=ord(k[num])-ord('A'); //需要偏移的位数
 sum:=ord(s[i])-sum; //偏移后的asc码
 if sum<65 then //若小于A要环形结构,+上26
  sum:=sum+26;
ans:=ans+chr(sum); //记录,也可以直接判断输出
end;

for i:=1 to lens do //处理答案,输出,可以和上步结合。
begin
 if down[i]=true then
  write(chr(ord(ans[i])+32))
 else
  write(ans[i]);
end;

//close(input);
//close(output);

end.

代码二:

program vigenere;
var k,c:ansistring;
    l,r,i,d:longint;
    f:array[1..1002] of longint;
begin
  //assign(input,'vigenere.in');reset(input);
  //assign(output,'vigenere.out');rewrite(output);
  readln(k); readln(c);
  fillchar(f,sizeof(f),0);
  l:=length(k); r:=length(c);
  for i:=1 to r do
    if ord(c[i])>96 then f[i]:=32; //将所有小写字母在f数组的相应位置加上32(大写字母与小写字母在ASC||码表中的差)
  k:=upcase(k); c:=upcase(c);    //upcase,将字符串里的字符全部改为大写
  for i:=1 to r do  //一个一个字母循环
    begin
      d:=(i-1) mod l+1; //密匙重复使用,是该数-1后modl 再加1;也可改为下列两句
      //inc(d);
      //if d=l+1 then d:=1;
      if c[i]<k[d] then write(chr(ord(c[i])-ord(k[d])+91+f[i]))  //密匙字母>密文字母,减完的结果是负的,+91,密文表从右往左看,再加上是否为小写的数字
        elsewrite(chr(ord(c[i])-ord(k[d])+65+f[i]));  //
密匙字母<密文字母,减完的结果是正的 ,+65,密文表从左往右看,再加上是否为小写的数字
    end;
  //close(input);close(output);
end.


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值