PAT (Basic Level) Practice 1048 数字加密

一、概述

给出两个数字A和B,按位分奇偶进行操作。很简略的一道题。其坑的程度对于我来说直逼PAT A1002。

二、分析

给出加密用正整数A以及待加密数B,从个位开始,以个位为第一位,分别按奇偶进行处理。好,到这里还是正常,接下来的隐藏条件就得一点一点猜了,如果两个数不一样长,会出现什么情况?

以下是我的猜测:

根据给出的例子,B比A长,B的剩余部分直接成为结果。则推测A比B长的时候不输出。结果测试点2和5过不去。

继续猜测。

A比B长的时候输出A的输出A的剩余部分。结果还是过不去。

继续猜测。

对于结果进行前面补零的操作,使得结果与较长的一样长。过不去。

继续猜测。

猜不出。

上网查询。

方法和我的都不一样,翻转过来再处理。

嗯?特殊之处在于对于不一样长的数,在后面补零。

卧槽,原来是A比B长的时候B要补零啊。那不就是按A的剩余输出吗?

不对,偶数是B-A,B为零那减完就是负数了,要加10!所以不是A的剩余部分成为结果,是10-A才对。

测试点2过了,5没过。

猜测问题还是出在这里。

偶然发现当B-A=0的时候,加10输出的是J而不是0,从而,最后的bug也被找到了。

如图

下面是我的算法:

我并没有使用翻转的方法,最开始觉得写一个函数太麻烦,后来才知道我是多么幼稚。

不翻转,那么数组的下标就会很复杂。

B比A长的情况下,如下

for (i = lengthB - 1; i >lengthB - lengthA - 1; i--)
{
	if ((lengthB - i) % 2 == 0)
		if (B[i] - A[lengthA - (lengthB - i)] >= 0)
    		Answer[i] = B[i] - A[lengthA - (lengthB - i)];
		else
			Answer[i] = B[i] - A[lengthA - (lengthB - i)] + 10;
	else
	{
	    Answer[i] = (A[lengthA - (lengthB - i)] + B[i] - 96) % 13;
    }
}
for (i = lengthB - lengthA - 1; i >= 0; i--)
	Answer[i] = B[i] - 48;
int m = 0;
while (num[Answer[m]] == '0')
	m++;
for (i = m; i < lengthB; i++)
{
	printf("%c", num[Answer[i]]);
}

个位作为第一位,那么就要从后向前来数,角标与第几位的转换关系也很容易弄混。另外,测试点没有首部出现多个零的情况,对于这一情况我也考虑到了,oj还是不够严密。

A比B长的情况下,如下

for (i = lengthB - 1; i >= 0; i--)
{
	if ((lengthB - i) % 2 == 0)
		if (B[i] - A[lengthA - (lengthB - i)] >= 0)
			Answer[lengthA - (lengthB - i)] = B[i] - A[lengthA - (lengthB - i)];
		else
			Answer[lengthA - (lengthB - i)] = B[i] - A[lengthA - (lengthB - i)] + 10;
	else
		Answer[lengthA - (lengthB - i)] = (A[lengthA - (lengthB - i)] + B[i] - 96) % 13;
}
for (i = lengthA - lengthB - 1; i >= 0; i--)
{
	/*if ((i + 1) % 2 != 0)
		Answer[i] = A[i] - 48;
	else
		if (A[i] == 0)
			Answer[i] = 0;
		else
			Answer[i] = 10 - (A[i] - 48);*/
	if((lengthA-i)%2!=0)
		Answer[i] = A[i] - 48;
	else
		if (A[i] == '0')//我就是个傻逼
			Answer[i] = 0;
		else
			Answer[i] = 10 - (A[i] - 48);
}
int m = 0;
while (num[Answer[m]] == '0')
	m++;
for (i = m; i < lengthA; i++)
{
	printf("%c", num[Answer[i]]);
}

数组下标如果不确定的话,就f10一步一步走,走两遍就能全改好了,真的靠算的话很费时间,还可能不对。

这里有一个小bug,就是我进行了string到char到int的转换,在检查是否为零时,开始0没加单引号,而且没检查出来,又多耗费了一点时间,很气。

三、总结

检查点不过的原因有很多,无外乎特殊值如0,1,最大值没考虑到;char转int没减48;字符串类的空字符串,满字符串等;还有一大部分是题意没理解好,这个是最坑的,多加一个样例可以节约很多很多时间。很是不愿放弃自己写了很久的代码。

PS:代码如下

#include<stdio.h>
#include<iostream>
#include<string>

using namespace std;

char num[13] = { '0','1','2','3','4','5','6','7','8','9','J','Q','K' };

int main()
{
	string A, B;
	cin >> A;
	cin >> B;
	int lengthA = A.length();
	int lengthB = B.length();
	int Answer[110] = { 0 };
	int count, answerl;
	int i;
	if (lengthA < lengthB)
	{
		for (i = lengthB - 1; i >lengthB - lengthA - 1; i--)
		{
			if ((lengthB - i) % 2 == 0)
				if (B[i] - A[lengthA - (lengthB - i)] >= 0)
					Answer[i] = B[i] - A[lengthA - (lengthB - i)];
				else
					Answer[i] = B[i] - A[lengthA - (lengthB - i)] + 10;

			else
			{
				Answer[i] = (A[lengthA - (lengthB - i)] + B[i] - 96) % 13;
			}
		}
		for (i = lengthB - lengthA - 1; i >= 0; i--)
			Answer[i] = B[i] - 48;
		int m = 0;
		while (num[Answer[m]] == '0')
			m++;
		for (i = m; i < lengthB; i++)
		{
			printf("%c", num[Answer[i]]);
		}
	}
	else
	{
		for (i = lengthB - 1; i >= 0; i--)
		{
			if ((lengthB - i) % 2 == 0)
				if (B[i] - A[lengthA - (lengthB - i)] >= 0)
					Answer[lengthA - (lengthB - i)] = B[i] - A[lengthA - (lengthB - i)];
				else
					Answer[lengthA - (lengthB - i)] = B[i] - A[lengthA - (lengthB - i)] + 10;

			else
				Answer[lengthA - (lengthB - i)] = (A[lengthA - (lengthB - i)] + B[i] - 96) % 13;
		}
		for (i = lengthA - lengthB - 1; i >= 0; i--)
		{
			/*if ((i + 1) % 2 != 0)
				Answer[i] = A[i] - 48;
			else
				if (A[i] == 0)
					Answer[i] = 0;
				else
					Answer[i] = 10 - (A[i] - 48);*/
			if((lengthA-i)%2!=0)
				Answer[i] = A[i] - 48;
			else
				if (A[i] == '0')//我就是个傻逼
					Answer[i] = 0;
				else
					Answer[i] = 10 - (A[i] - 48);
		}
		int m = 0;
		while (num[Answer[m]] == '0')
			m++;
		for (i = m; i < lengthA; i++)
		{
			printf("%c", num[Answer[i]]);
		}
	}
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值