8 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
        @ 2024-12-6 21:49:48
        #include<stdio.h>
        
        int main()
        {
            int n,i,j,k,L;
            char l,id[18];
            scanf("%d \n", &n);
          
            for(i=0;i<n;i++)
            {
                for (j = 0; j < 17; j++)
                {
                    scanf("%c", &id[j]);
                }
             scanf("%c \n", &l);
             if(l=='X')
             {
                 L = 10;
             }
             else{L=l-'0';}
            int sum = 0,t=16,prime;
           while (t>=0)
            {
                prime = id[t] - '0';
                
                switch (t)
                {
                case 16:sum += (2 * prime); break;
                case 15:sum += (4 * prime); break;
                case 14:sum += (8 * prime); break;
                case 13:sum += (5 * prime); break;
                case 12:sum += (10 * prime); break;
                case 11:sum += (9 * prime); break;
                case 10:sum += (7 * prime); break;
                case 9:sum += (3 * prime); break;
                case 8:sum += (6 * prime); break;
                case 7:sum += (1 * prime); break;
                case 6:sum += (2 * prime); break;
                case 5:sum += (4 * prime); break;
                case 4:sum += (8 * prime); break;
                case 3:sum += (5 * prime); break;
                case 2:sum += (10 * prime); break;
                case 1:sum += (9 * prime); break;
                case 0:sum += (7 * prime); break;
                }
                t--;
            }
            int M=sum%11;
            switch (M)
            {
            case 0:k=1; break;
            case 1:k=0; break;
            case 2:k=10; break;
            case 3:k=9; break;
            case 4:k = 8; break;
            case 5:k = 7; break;
            case 6:k = 6; break;
            case 7:k = 5; break;
            case 8:k = 4; break;
            case 9:k = 3; break;
            case 10:k = 2; break;
            }
            if(k==L)
            {
            printf("True\n");
            }
            else{ printf("False\n");}
            }
            return 0;
        }
        

        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
                  1800
                  Accepted
                  230
                  Uploaded By