8 solutions
-
2
P1037. 中国身份证号码校验
了解到一部分同学不懂ASCII码,于 10.20 更新一份ASCII码说明
题意概述
省份证号码存在一位校验码,这位校验码是使用号码的前17位数字通过数乘、求和后取余11得到数字又会去对应一个数,这个数就是校验码。
题意分析
这里,我第一眼想到的解决方案是使用打表(或许这就是蒟蒻的特点吧!),我打了几个后....算了,为了偷懒换了一个打表方式,将需要数乘和结果对应的数列放到数组里面。(简单提一下,不会有人用long long来存储省份证号吧!应为省份证号中有X,我们就不使用int型变量,用字符数组存储)。
比如,:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2,就可以建立一个数组存储,然后根据循环时角标一一对应即可。另外的数列同理。
这里说一下我怎么处理X的,在后面做特判也是可以的,我是直接把X换成('9'+1)这样子可以省点代码。
可行代码
#include <iostream> using namespace std; int main(){ int T; cin >> T; while(T--){ char num[20]; cin >> num; if(num[17] == 'X') num[17] = '9' + 1; int cs[] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; int res[] = {1,0,10,9,8,7,6,5,4,3,2}; int sum = 0; for(int i = 0; i < 17; i++){ sum += (num[i] - '0') * cs[i]; } sum %= 11; if(res[sum] + '0' == num[17]) cout << "True" << endl; else cout << "False" << endl; } return 0; }
EDN 看到这个题AC率一路下滑,就来发一篇题解,看不懂的私聊我。AC每一天!
ASCII
美国信息交换标准代码(American Standard Code for Information Interchange)
简单引入
如果只是想简单了解使用的话,直接跳转到 ASCII码的特点
众所周知,计算机硬件决定了计算机它只懂二进制,也就是计算机内实际上所有的东西都是(0/1)组成。包括我们的字符也是这样子,那么这些字符在计算机内如何表示呢?C语言是一门开放的语言,在这里面字符仅仅是字符吗?希望你看到这里带着这两个问题去思考。
认识char
大家都学习了char这种数据类型,我们都知道它可以存储字符。但是,其内部结构如何呢?
我们来浅显的(知识有限只能浅显)分析一下:
计算机内只能存储(0/1),之前我们也学到char是一个字节(1B),也就是说char数据类型有1B的空间。在1B的空间内可以存储8个位,每个位有两种状态也就是(0/1)。
那么我们是否可以建立一套规则来用8个位的不同状态来表达不同的字符呢?是的,字符编码规则就和这差不多。
ASICC码规定字符 '0' 的码为下面这一串 01 串:
根据不同的01串表达方式不同状态表达不同字符,利用与 '0' 相同的方法建立一套字符表达体系:
可以看到每个字符会对应一个十进制整数,那就是它的编码。
我们来算一笔帐,表中所给出的字符应该是有 128 个吧!但是我们上文提到, char 有八个位应该可以表达 256 种情况,其实最高位和 int 有异曲同工之妙,都是符号位!
这里也可以看出, char 和 int 是相通的。我们不妨对 char 的 01 串用二进制的方式来算一算:
正好是(2^5 × 1) + (2^4 × 1) + (2^3 × 0) + 0 + 0 + 0 = 48
所以实际上我们可以将 char 也视作是数字,但是比较特殊。当你使用 %d 输出发现是整数,用 %c 输出发现是字符,其实就是看你在不同情况下如何看待这一个01串。
char ch = '0'; printf("%d\n", ch); // 输出 48 printf("%c\n", ch); // 输出 0
ASCII码的特点
可以看到这里面有很多不认识的字符,一些熟悉的字符。前面一大部分字符都是都是没有具体表达形式,但是,它们具有自己的功能。除了需要了解 NULL 的 ASCII 码为 0 外,前面没太多需要注意(只针对在我们这些竞赛领域)。大部分的字符都是不需要记住的,一般来说,知道 '0' 是 48 就很好推出每一个数字的值,但是大多数时候我们直接使用 '0' 来表示而不使用 48 表示。还有就是 'a' 和 'A' 的编码也可以记一记。
我们回到这个题目的题解,当 num[17] == 'X' 的时候,我们将 num[17] 赋值为 ('9' + 1) , '9' 的编码加一,查表发现对应的是 ':' ,但是我们这里只是判断结果 sum 是否为 10,我们可以 (':' - '0') 来表示 10 对吧,实在不理解就是(58 - 48)。同理可得到,前面那些 ( - '0' )的操作就是将ASCII码的编码减小成为对应的整数,来进行数学运算。
其实在我们学习中,很多时候会遇到,输入的是字符型的数字,但是我们要用其进行数学运算,就像是我们想表达 (9 + 1)结果为 10 ,但是我们使用字符来表达 ('9' + '1')其计算方式就是编码相加(57 + 49)结果不言而喻了吧!此时我们做一个操作(('9' - '0') + ('1' - '0'))不就可以将字符当作整数做运算了吗。
另外一个值得记住的点就是大小写字符之间的关系,细心的同学在看表的时候已经发现了,大小写字符在表格中的位置是一一对应的,我们将其做差和明显的发现,他们之间的差值是 32 ,基于这个特点我们常常用来做字母大小的转换。
Information
- ID
- 41
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 8
- Tags
- # Submissions
- 1800
- Accepted
- 230
- Uploaded By