题目
L1-016 查验身份证 (15分)
题目链接
题目大意
中文题意,具体内容见PTA
题解
-
为什么对L1题写题解?
毫无疑问,这是一题十分简单的题目,然而我花费的时间却多了一点,其中就在于细节的处理,在做模拟类型的题目的时候,细节的处理和对于题目的阅读是十分关键的,所以对此做一个记录。 -
需要注意的点
- 加权求和 ,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};这是题目所给的,我们直接加权求和即可,不必再在加权求和后再进行除100的运算,那样纯属多次一举,可能会导致加权求和所得和数有误
关于
最后按照以下关系对应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
这种对应匹配应该怎么处理?因为处理方法实在是太多了,一下子也十分难以判断哪种最快,因为在简单的情况下,能写的越加简便就越有利,那么我归纳为两种方法
由于Z的值是0~10刚好符合数组下标所以直接用字符数组进行存储
- 第一种
char z[] = {'1','0','X','9','8','7','6','5','4','3','2'};
由于map在对于数据对应的处理上具有得天独厚的优势,所以用map也十分的合理
map<int, char> cp = {{0, '1'}, {1, '0'}, {2, 'X'}, {3, '9'}, {4, '8'},
{5, '7'}, {6, '6'}, {7, '5'}, {8, '4'}, {9, '3'}, {10, '2'}};
这两种处理方法都是比较不错,也清晰易懂
题目要求前17位都是数字,并且最后一位符合匹配,所以我拆为两个函数进行处理,使得代码更加清晰易懂
- 问: 两个bool函数进行处理,那时间复杂度上会不会更大呢?
- 答:在书写代码的时候,我也特地思考了下这个问题,答案是不会有太大影响,并且一定程度上时间复杂度更小
- 因为在判断不是全数字进行情况下我就直接进行下一个字符串的处理了
- 那在全数字判断完再进行求和,这与合起处理的时间复杂度是一样的,综上 无差
代码
#define rep(i, a, b) for (int i = a; i <= b; ++i)
int weight[] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
char z[] = {'1','0','X','9','8','7','6','5','4','3','2'};
bool judge_digit(string s){
rep(i, 0, 16){
if (s[i] < '0' || s[i] > '9') return false;
}
return true;
}
bool judge_lastplace(string s) {
int wsum = 0;
rep(i, 0, 16){
wsum += weight[i] * (s[i] - '0');
}
//wsum /= 100;
wsum += 11;
wsum %= 11;
if (s[17] == z[wsum]) return true;
else return false;
}
int main(){
int _;
bool ap = true;
for(scanf("%d", &_); _; _--){
string s; cin >> s;
if (judge_digit(s)) {
if (!judge_lastplace(s)) {
cout << s << '\n';
ap = false;
}
}
else{
cout << s << '\n';
ap = false;
}
}
if (ap) cout << "All passed" << '\n';
}