7 solutions

  • 2
    @ 2021-10-17 18:00:10

    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 串: '0'的内部结构

    根据不同的01串表达方式不同状态表达不同字符,利用与 '0' 相同的方法建立一套字符表达体系:

    ASCII 可以看到每个字符会对应一个十进制整数,那就是它的编码。

    我们来算一笔帐,表中所给出的字符应该是有 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 ,基于这个特点我们常常用来做字母大小的转换。

    • 1
      @ 2022-3-15 20:05:20

      有没有c的解法呀

      • 0
        @ 2023-10-14 21:47:03
        #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
          @ 2022-4-8 22:21:48
          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
            @ 2022-4-4 17:17:55

            理清思路应该不难

            #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
              @ 2022-3-7 20:38:45
              #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
                @ 2021-10-17 15:17:38

                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