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をちゃんと使おうと心に決めました。