【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; }