【GPLT】L1-016【PAT乙級】查驗身份證

  • 2019 年 11 月 8 日
  • 筆記

版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/weixin_42449444/article/details/84866000

題目描述:

一個合法的身份證號碼由17位地區,日期編號和順序編號加1位校驗碼組成校驗碼的計算規則如下: 首先對前17位數字加權求和,權重分配為:{7,9, 10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然後將計算的和對11取模得到值Z者除外;最後按照以下關係對應ž值與校驗碼M的值: Z:0 1 2 3 4 5 6 7 8 9 10 M:1 0 X 9 8 7 6 5 4 3 2 現在給定一些身份證號碼,請你驗證校驗碼的有效性,並輸出有問題的號碼。

輸入描述:

輸入第一行給出正整數N(<= 100)是輸入的身份證號碼的個數。隨後N行,每行給出1個18位身份證號碼。

輸出描述:

按照輸入的順序每行輸出1個有問題的身份證號碼。這裡並不檢驗前17位是否合理,只檢查前17位是否全為數字且最後1位校驗碼計算準確。如果所有號碼都正常,則輸出「All passed」。

輸入樣例:

4  320124198808240056  12010X198901011234  110108196711301866  37070419881216001X

輸出樣例:

12010X198901011234  110108196711301866  37070419881216001X

解題思路:

首先,這個題目看起我有點懵逼,真的題目都看了3,4遍。好好縷了下思路之後,先建立倆個數組分別用來存放權值分配和校驗碼M。然後取消cin與stdin的同步壓壓驚,真的怕TLE,畢竟要對若干個18位數的身份證每一位進行校驗。立個標誌=真,如果到最後,標誌還是為真,表明所有的身份證號碼都正常,輸出「All passed」。然後isTrue用來判斷每一個身份證號的前17位是否全為數字,若不是數字則isTrue和flag都變成false,用sum來計算身份證號號的每一位數和它所佔的權值的乘積之和,將計算出來的總和對11取模得到值Z,根據題意可知,可以根據ž值來找到對應的校驗碼中號的值,若IsTrue運算為真但校驗碼中號和身份證最後一位不相等,這個身份證號也是錯誤的,需要對錯誤的身份證號進行輸出。

AC程式碼:

#include <bits/stdc++.h>  using namespace std;    int weight[17] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};  char M[11] = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};    int main()  {      ios::sync_with_stdio(false);      int n;      cin >> n;      string ID;      bool flag = true;      for (int i = 0; i < n; i++)      {          int sum = 0;          bool isTrue = true;          cin >> ID;          for(int j = 0; j < 17; j++)          {              if(ID[j]<'0'||ID[j]>'9')              {                  cout << ID << endl;                  flag = false;                  isTrue = false;                  break;              }              sum += (ID[j]-'0')*weight[j];          }          int z = sum%11;          if(ID[17]!=M[z] && isTrue)          {              flag = false;              cout << ID << endl;          }      }      if(flag)      {          cout << "All passed" << endl;      }      return 0;  }