SRM583 Div2 medium IDNumberVerification
問題
18ケタのIDが与えられます。コードが男性を表すものか女性を表すものか、それとも不正コードかを判定しなさい。
上6ケタはエリアコードです。regionCodesの中のどれかです(regionCodesになければ不正コードです)。
次の8桁は誕生日です。yyyymmddです。1990/01/01~2011/12/31までの存在する日付でなければ不正コードです。
次の3桁はシーケンシャルな番号です。"000"のみ不正コードです。
これが奇数だと男性、偶数だと女性です。
最後の1桁はチェックサムです。
IDをa0a1a2 ... a17と表すことにすると、
a0*2^17+a1*2^16+ ... +a17≡1(mod 11)
となってほしいです。これは0-9の数字か'X'(10を表す)が入っています。
解法
真面目に全部チェックしていけばOKです。うるう年とかめんどいけどまあめんどいだけです。
プログラム
#include <sstream> #include <string> #include <vector> #include <map> #include <algorithm> #include <iostream> #include <utility> #include <set> #include <cctype> #include <queue> #include <stack> #include <cstdio> #include <cstdlib> #include <cmath> using namespace std; #define li long long int #define rep(i,to) for(int i=0;i<((int)(to));i++) #define repp(i,start,to) for(int i=(int)(start);i<((int)(to));i++) #define pb push_back #define sz(v) ((li)(v).size()) #define allof(v) (v).begin(),(v).end() #define p2(a,b) cout<<a<<"\t"<<b<<endl class IDNumberVerification { public: string verify(string id, vector <string> regionCodes) { string r=id.substr(0,6); string y=id.substr(6,4); string m=id.substr(10,2); string d=id.substr(12,2); string s=id.substr(14,3); li summ=(id[17]=='X' ? 10 : id[17]-'0'); bool rv=false; rep(i,sz(regionCodes)){ if(r==regionCodes[i]){ rv=true; break; } } if(!rv){ return "Invalid"; } if(y<"1900" || y>"2011")return "Invalid"; li yyyy=(y[0]-'0')*1000+(y[1]-'0')*100+(y[2]-'0')*10+(y[3]-'0'); li mm=(m[0]-'0')*10+(m[1]-'0'); li dd=(d[0]-'0')*10+(d[1]-'0'); li hi[12]={31,28,31,30,31,30,31,31,30,31,30,31}; if((yyyy%4==0 && yyyy%100!=0) || yyyy%400==0)hi[1]=29; if(dd>hi[mm-1])return "Invalid"; if(mm<1 || mm>12 || dd<1)return "Invalid"; if(s=="000")return "Invalid"; string res; if((s[2]-'0')%2==1)res="Male"; else res="Female"; li sum=0; rep(i,17){ sum+=id[i]-'0'; sum*=2; sum=sum%11; } sum+=summ+10; cout<<sum<<endl; if(sum%11!=0)return "Invalid"; return res; } };
雑感
本番では日付判定に満足して
if(mm<1 || mm>12 || dd<1)return "Invalid";
を忘れて落ちました。アホか。
条件が多いだけの問題だったので注意して確認すべきでした。
そしてreturn "Invalid"; が多すぎてコードが汚くてよろしくないですね。。
あと文字列→数字の変換があまりに愚かなのでstringstreamかatoiをちゃんと使おうと心に決めました。