Description
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
111111191110111111111111111111111
直接枚举所有可能就好了。
#include<stdio.h> #include<cstring> #include<algorithm> #include<map> using namespace std; map<int,int> m; 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 begin() { scanf("%d",&T); 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++) m[10000*i+j*100+k]=1; } 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; for (int k=1;k<=lim;k++) m[10000*i+j*100+k]=1; } } } char check() { int sum=0; for (int i=0;i<17;i++) { sum+=(s[i]-'0')*b[i]; } sum=(12-(sum%11))%11; if (sum==10) return 'X'; return '0'+sum; } void work() { int tot=0; for (int i=6;i<=11;i++) tot=tot*10+s[i]-'0'; if (m.count(tot)) {printf("%s\n",s); return;} 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++) { 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 tot=0,p=0; for (int i=6;i<=13;i++) tot=tot*10+s[i]-'0'; if (m.count(tot)) { s[17]=check(); printf("%s\n",s); return; } 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; for (int k=1;k<=lim;k++) { tot=0; p=N; 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+=(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() { begin(); while (T--) { scanf("%s",s); if (strlen(s)==15) work(); else get(); } return 0; }