7 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 ,基于这个特点我们常常用来做字母大小的转换。
-
0
#include<iostream> using namespace std; int main(){ int n; cin>>n; char arr[18]; int a[17]; for(int i=0;i<n;i++){ int sum=0; cin>>arr; for(int j=0;j<17;j++){ a[j]=arr[j]-48;//字符型变量可以当成整型用,0~9作为字符对应的ASCII码是48~57 } sum=a[0]*7+a[1]*9+a[2]*10+a[3]*5+a[4]*8+a[5]*4+a[6]*2+a[7]*1+a[8]*6+a[9]*3+a[10]*7+a[11]*9+a[12]*10+a[13]*5+a[14]*8+a[15]*4+a[16]*2; sum%=11;//把和转化成余数了 if(arr[17]=='X'){ if(sum==2)cout<<"True"<<endl; else cout<<"False"<<endl; } else{ if(arr[17]-48==(12-sum)%11)cout<<"True"<<endl; else cout<<"False"<<endl; } } return 0; }
-
0
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); for (int j = 0; j < n; j++) { String s = sc.next(); int sum = 0; int[] nums = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 }; for (int i = 0; i < nums.length; i++) { int a = s.charAt(i) - '0'; sum += a * nums[i]; } int mod = sum % 11; String s1 = "10X98765432"; if (s.charAt(17) == s1.charAt(mod)) { System.out.println("True"); } else { System.out.println("False"); } } sc.close(); } }
-
0
理清思路应该不难
#include <iostream> using namespace std; int f[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; char d[11]={'1','0','X','9','8','7','6','5','4','3','2'}; int main() { int n = 0; cin >> n; while(n--) { char s[18]; int i = 0; for(i = 0; i < 18; i++) cin >> s[i]; int sum = 0; for(i = 0; i < 17; i++) { if(s[i] == 'X') sum += (f[i]*10)%11; else sum += ((s[i]-'0')*f[i])%11; } sum %= 11; if(d[sum] == s[17]) cout << "True" << endl; else cout << "False" << endl; } return 0; }
-
0
#include <stdio.h> #include <algorithm> #include <math.h> #include <vector> #include <iostream> using namespace std; int n,a[18]= {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; string s; int y[12]= {1,0,0,9,8,7,6,5,4,3,2}; int main() { scanf("%d",&n); for(int i=0; i<n; i++) { cin>>s; int sum=0; for(int j=0; j<17; j++) { sum+=(s[j]-'0')*a[j]; } int tmp=sum%11; if(tmp==2) { if(s[17]=='X') printf("True\n"); else printf("False\n"); } else { int r=s[17]-'0'; if(r==y[tmp]) printf("True\n"); else printf("False\n"); } } return 0; }
-
0
def checkIDNumber(num): xishu = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]#17个 weihao= [1,0,'X',9,8,7,6,5,4,3,2]#11个 ls=list(map(int,num[:17])) qiuhe=list(map(lambda x,y:x*y,xishu,ls)) temp=sum(qiuhe)%11 if num[17]==str(weihao[temp]): print('True') else: print('False')
if name == 'main': data=[] n=input() #总共个数 for i in range(int(n)): a=input()#身份证号码 data.append(a) for x in range(len(data)): checkIDNumber(data[x])
- 1
Information
- ID
- 41
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 8
- Tags
- # Submissions
- 1756
- Accepted
- 225
- Uploaded By