Mr. Wu, the inspector of the district, is really angry for a robbery happened last night. The robber escaped while Mr. Wu knows nothing about him. The only clue Mr. Wu has is a photo of the robber, which is recorded by the security camera.
Fortunately, the robber was seen by a witness in a train station, and his identity card was captured on a video camera when he was passing security check. As you know, each identity card in China has a unique identification number. Therefore Mr. Wu can easily find who the robber is by looking up the ID in computer database. But he failed, and found the number was not in the database. He guesses some digits in the identification number are misinterpreted because the picture of the robber's identity card is in bad quality.
To find the original identification number, Mr. Wu assumes that only a minimal number of characters are misinterpreted. While this assumption may be reasonable, he finds it hard for him to determine the correct number. So he turns you, a talented programmer, to help him find the correct answer.
To accomplish this task, you need to have some basic knowledge about identity cards used in China. There are two number system used for identification number, namely the first generation and the second generation. The first generation consists of a 15-digit code while the second generation consists of an 18-digit code. See following tables for details.
1 | 2 | 3 | 4 | 5 | 6 | Y | Y | M | M | D | D | 8 | 8 | 8 |
Address code | Date of Birth | Order code |
1 | 2 | 3 | 4 | 5 | 6 | Y | Y | Y | Y | M | M | D | D | 8 | 8 | 8 | X |
Address code | Date of Birth | Order code | Checksum |
The identification number must obey the following constraints:
- The address code refers to the resident's location. For simplicity, here we consider any digits are legal.
- The Date of Birth must be a legal date. Since the robbery happened last night, we assume any date from Jan 1, 1900 to Apr 2, 2011 (inclusive) is legal, and others are illegal. For identification number in first generation card, the first 2 digits of year are omitted, and the date is considered legal if one of the two interpretations (19xx or 20xx) is legal.
- Order code is the code used to disambiguate people with the same date of birth and address code. We consider any digits are legal.
- Checksum confirms the validity of the ID number from the first 17 digits in second generation identity card. It is calculated by:
- Mark the identification code right-to-left a1, a2, ... , a18. a1 is the checksum digit.
- Calculate coefficient for each digit: Wi = 2i - 1 mod 11. For simplicity, Wi is given in the following table:
i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 Wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1 - Calculation of
- a1 = (12 - (S mod 11)) mod 11
- If a1 is between 0 and 9, the checksum code is a1 itself. If a1 is 10, the checksum code is "X" (upper case).
Now given an identification number either in 15-digit format or 18-digit format, you need to output a legal identification number by changing minimal number of digits in original one.
Input
There are multiple test cases. The first line of input is an integer T ≈ 100 indicating the number of test cases.
Each test case consists of a line of identification number, in either 15-digit format or in 18-digit format. All characters are digits except the last character in an 18-digit-format code may be a capital 'X'. There will be no extra characters.
Output
For each test case, you need to output the correct identification number described above. If there are multiple solutions, any one is OK.
Sample Input
2 111111111111111111 111111111111111
Sample Output
111111191110111111 111111111111111
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4282
#include<iostream>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<queue>
#include<string.h>
#include<stdlib.h>
#include<cstdio>
#define ll long long
using namespace std;
int T;
int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int b[20]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1};
char s[20];
void work(){
int n=0x7FFFFFFF,N;
for (int i=0;i<=99;i++){
for (int j=1;j<=12;j++){
int limit=a[j]+((j==2&&i%4==0)?1:0);
for (int k=1;k<=limit;k++){
int tot=0;
if (i/10!=s[6]-'0') tot++;
if (i%10!=s[7]-'0') tot++;
if (j/10!=s[8]-'0') tot++;
if (j%10!=s[9]-'0') tot++;
if (k/10!=s[10]-'0') tot++;
if (k%10!=s[11]-'0') tot++;
if (tot<n) {n=tot; N=10000*i+j*100+k;} //存年月日
}
}
}
for (int i=0;i<6;i++) printf("%c",s[i]);
printf("%06d",N);
for (int i=12;i<15;i++) printf("%c",s[i]);
printf("\n");
}
void get(){
int n=0x7FFFFFFF,N=0,M;
char c,d;
for (int i=0;i<17;i++) //计算后一位
if (i<6||i>13) N+=b[i]*(s[i]-'0');
for (int i=1900;i<=2011;i++){
int limit=(i==2011)?4:12; //妙
for (int j=1;j<=limit;j++){
int lim=a[j]+((j==2&&i%4==0)?1:0); //妙
if (i==1900&&j==2) lim=28;
if (i==2011&&j==4) lim=2; //截止日期 2011.4.2
for (int k=1;k<=lim;k++){
int tot=0; int p=N; //tot是存当前的号码和样例有几位不同
if (i/1000!=s[6]-'0') tot++;
if ((i/100)%10!=s[7]-'0') tot++;
if ((i/10)%10!=s[8]-'0') tot++;
if (i%10!=s[9]-'0') tot++;
if (j/10!=s[10]-'0') tot++;
if (j%10!=s[11]-'0') tot++;
if (k/10!=s[12]-'0') tot++;
if (k%10!=s[13]-'0') tot++;
p+=(i/1000)*(b[6]);
p+=(i/100)%10*(b[7]);
p+=(i/10)%10*(b[8]); //p是用来求最后一位的
p+=(i%10)*(b[9]);
p+=(j/10)*b[10];
p+=(j%10)*b[11];
p+=(k/10)*b[12];
p+=(k%10)*b[13];
p=(12-p%11)%11;
if (p==10) c='X'; else c='0'+p;
if (c!=s[17]) tot++;
if (tot<n){n=tot; M=10000*i+j*100+k; d=c;}
}
}
}
for (int i=0;i<6;i++) printf("%c",s[i]);
printf("%08d",M); //年月日
for (int i=14;i<17;i++) printf("%c",s[i]);
printf("%c\n",d); //最后一位
}
int main(){
cin>>T;
while (T--){
scanf("%s",s);
if (strlen(s)==15) work();
else get();
}
return 0;
}