zoj 3485 Identification Number身份证(模拟)

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.

Number system for the first generation identity card
123456YYMMDD888
Address codeDate of BirthOrder code
Number system for the second generation identity card
123456YYYYMMDD888X
Address codeDate of BirthOrder codeChecksum

The identification number must obey the following constraints:

  1. The address code refers to the resident's location. For simplicity, here we consider any digits are legal.
  2. 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.
  3. Order code is the code used to disambiguate people with the same date of birth and address code. We consider any digits are legal.
  4. Checksum confirms the validity of the ID number from the first 17 digits in second generation identity card. It is calculated by:
    1. Mark the identification code right-to-left a1a2, ... , a18a1 is the checksum digit.
    2. Calculate coefficient for each digit: Wi = 2i - 1 mod 11. For simplicity, Wi is given in the following table:
      i181716151413121110987654321
      Wi79105842163791058421
    3. Calculation of S = \sum_{i=2}^{18} a_i * W_i
    4. a1 = (12 - (S mod 11)) mod 11
    5. 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;  
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值