2009-02-08
拙作bignumライブラリを使って昨日のMedium問題を解いてみる
library | |
string replace(const string s, int a, int b){ stringstream ss; int l=s.size(); for(int i=0;i<l;i++){ int c=s[i]; ss << (char)((c==a)? b : c); } return ss.str(); } char en(int c){ if (c<10) return '0'+c; else return 'A'+(c-10); } class HexatridecimalSum { public: string maximizeSum(vector<string> numbers, int k) { vector<bignum> ofs(36); rep(i,36) ofs[i]=0; bignum sum; tr(numbers,it){ string orig_str = *it; bignum b(orig_str,36); sum += b; rep(i,36){ bignum b_(replace(orig_str,en(i),'Z'),36); ofs[i] += (b_ - b); } } sort(all(ofs)); reverse(all(ofs)); rep(i,k) sum += ofs[i]; return sum.to_s(36); } };
System Testも難なく通りました。
bignumライブラリの自作
- bignum同士の加減乗算(※除算は未実装)
- bignumに(signed)intを足したり引いたり掛けたり割ったり
- bignumと文字列との間の変換(基数指定可)
とか。とりあえず、昨日のMedium問題が解ける程度まで実装できたので晒します。
内部では65536進法で演算しています。2^32進法だと(bignum同士の加算や乗算をする際に)キャリーの計算が面倒くさいかなと思っての愚行です。
ご利用は計画的に。
// // bignum library ver 0.1 by naoya_t - 使うなら自己責任で // #include <string> #include <vector> #include <stack> #include <sstream> #include <iostream> using namespace std; class bignum { int sign; int size; vector<int> values; int default_radix_; int remainder_; public: bignum(int val=0){set(val);default_radix_=10;} bignum(string val, int radix=10){set(val,default_radix_=radix);} bignum(const bignum& num){set(num);} bignum(int sg,const vector<int> &vals,int radix=0){set(sg,vals,radix);} void operator=(int val){set(val);} void operator=(string val){set(val,default_radix_);} void operator=(const bignum& num){set(num);} void set(int val); void set(string val, int radix=10); void set(const bignum& num); void set(int sg,const vector<int> &vals,int radix=0); private: bool is_zero() const { return (size==1 && values[0]==0)? true : false; }; void set_zero(); void normalize(); char enc(int n) const { return n<10 ? '0'+n : 'A'+(n-10); } int dec(int ch) const { return ch<='9' ? ch-'0' : 10+ch-'A'; } public: void set_default_radix(int radix){default_radix_=radix;} int get_default_radix(){return default_radix_;} string sdump() const; void dump() { cout << sdump(); } bignum abs() const; bignum minus() const; int cmp(const bignum &n) const; int cmp_abs(const bignum &n) const; int to_i(); string to_s(int radix=10) const; bignum operator+(const bignum& rop){ bignum num(*this); num += rop; return num; } bignum operator-(const bignum& rop){ bignum num(*this); num += rop.minus(); return num; } bignum operator*(const bignum& rop){ bignum num(*this); num *= rop; return num; } bignum operator+(int rop){ bignum num(*this); num += rop; return num; } bignum operator-(int rop){ bignum num(*this); num -= rop; return num; } bignum operator*(int rop){ bignum num(*this); num *= rop; return num; } bignum operator/(int rop){ bignum num(*this); num /= rop; return num; } bool operator==(const bignum& rop) const { return cmp(rop)==0; } bool operator!=(const bignum& rop) const { return cmp(rop)!=0; } bool operator>(const bignum& rop) const { return cmp(rop)>0; } bool operator>=(const bignum& rop) const { return cmp(rop)>=0; } bool operator<(const bignum& rop) const { return cmp(rop)<0; } bool operator<=(const bignum& rop) const { return cmp(rop)<=0; } void operator+=(const bignum& num); void operator-=(const bignum& num){ operator+=(num.minus()); } void operator*=(const bignum& num); //void operator/=(const bignum& num); void operator+=(int n); void operator-=(int n){ operator+=(-n); } void operator*=(int n); void operator/=(int n); //void operator%=(int n); int remainder(){ return remainder_; } bignum add(const bignum& n){ bignum num(*this); num += n; return num; } bignum sub(const bignum& n){ bignum num(*this); num += n.minus(); return num; } bignum mul(const bignum& n){ bignum num(*this); num *= n; return num; } //bignum div(const bignum& n){ bignum num(*this); num /= n; return num; } bignum add(int n){ bignum num(*this); num += n; return num; } bignum sub(int n){ bignum num(*this); num += (-n); return num; } bignum mul(int n){ bignum num(*this); num *= n; return num; } bignum div(int n){ bignum num(*this); num /= n; return num; } }; void bignum::set(int val){ if (val == INT_MIN) { values.resize(size = 2); sign = -1; values[0] = 0; values[1] = 0x8000; } else { if (val < 0) { sign = -1; val = -val; } else sign = 1; if (val >= 65536) { values.resize(size = 2); values[0] = val % 65536; values[1] = val >> 16; } else { values.resize(size = 1); values[0] = val; } } } void bignum::set_zero(){ values.resize(size = 1); size = 1; sign = 1; values[0] = 0; } void bignum::set(const bignum& num){ values.assign(num.values.begin(), num.values.end()); sign = num.sign; size = num.size; default_radix_ = num.default_radix_; } void bignum::set(int sg,const vector<int> &vals,int radix){ if (radix == 0) { size=1; for(int i=0,s=vals.size();i<s;i++) if (vals[i]>0) size=i+1; values.assign(vals.begin(), vals.begin()+size); sign = is_zero()? 1 : sg; } else { set_zero(); } } int bignum::to_i() { switch(size){ case 1: return sign * values[0]; case 2: if (values[1]<=0x7fff) return sign * ((values[1]<<16) | values[0]); else if (values[1]==0x8000 && values[0]==0 && sign==-1) return INT_MIN; else ; // else ; thru default: return INT_MAX+1; } } string bignum::sdump() const { stringstream ss; ss << ((sign > 0) ? "+" : "-") << hex << uppercase; for (int i=0;i<size;i++) { if (i>0) ss << ":"; ss << values[size-i-1]; } ss << "<" << size << ">"; return ss.str(); } bignum bignum::abs() const { bignum num(*this); num.sign = 1; return num; } bignum bignum::minus() const { bignum num(*this); if (!is_zero()) num.sign = -num.sign; return num; } int bignum::cmp(const bignum &n) const { if(sign != n.sign) return (sign - n.sign)/2; return sign * cmp_abs(n); } int bignum::cmp_abs(const bignum &n) const { if(size!=n.size) return size - n.size; for(int i=size-1;i>=0;i--) if(values[i]!=n.values[i]) return values[i] - n.values[i]; return 0; } void bignum::operator+=(const bignum &n){ if(n.is_zero()) return; if(sign == n.sign) { if(size < n.size) { values.resize(n.size); for(int i=size;i<n.size;i++) values[i]=0; size = n.size; } // simple addition for(int i=0;i<n.size;i++) values[i] += n.values[i]; } else { if(cmp_abs(n) >= 0) { for(int i=0;i<n.size;i++) { if (values[i] >= n.values[i]) { values[i] -= n.values[i]; } else { int pl=i+1; for(int j=i+1;j<n.size;j++) if(values[j]>0){ pl=j; break; } for(int j=pl;j>i;j--) { values[j]--; values[j-1]+=65536; } values[i] -= n.values[i]; } } } else { bignum t(n); set(t + *this); } } normalize(); } void bignum::operator*=(const bignum &n){ if(is_zero()) return; if(n.is_zero()){ set_zero(); return; } sign *= n.sign; vector<int> tmp(size + n.size, 0); for(int i=n.size-1;i>=0;i--){ int ni = n.values[i]; for(int j=size-1;j>=0;j--){ unsigned int ij = (unsigned int)ni * values[j]; tmp[i+j] += ij % 65536; tmp[i+j+1] += ij >> 16; } } values.assign(tmp.begin(), tmp.end()); size += n.size; normalize(); } void bignum::operator+=(int n){ if (n==0) return; if (sign*n<0){ int m=this->to_i(); if (m!=INT_MAX+1){ set(m + n); return; } } if(sign==-1) n=-n; values[0] += n; normalize(); } void bignum::operator*=(int n){ if(n==0){ set_zero(); return; } if(n==1){ return; } if(n==-1){ sign=-sign; return; } if(n<0){ sign=-sign; n=-n; } for(int i=0;i<size;i++) values[i]*=n; normalize(); } void bignum::operator/=(int n){ if(n==0){ set_zero(); return; } // NaN if(n==1){ return; } if(n==-1){ sign=-sign; return; } if(n<0){ sign=-sign; n=-n; } int r = 0; for(int i=size-1; i>=0; i--){ int v = (r << 16) + values[i]; r = v % n; values[i] = v / n; } normalize(); remainder_ = r; } void bignum::normalize(){ unsigned int overflown=0; int sz=1; for(int i=0;i<size;i++){ if (values[i]>0) sz=i+1; if (values[i]<0) { if (i==size-1) { // underflow sign=-sign; values[i]=-values[i]; for (int j=i-1;j>=0;j--){ //... } } else { // borrowable int b=-values[i]; values[i+1] -= (b >> 16); if (b&0xffff){ values[i+1]--; values[i] = 65536 - b; } else { values[i] = 0; } } } if (values[i]>=65536){ if (i==size-1) overflown = values[i] >> 16; else values[i+1] += values[i] >> 16; values[i] %= 65536; } } if (overflown == 0) { if (sz<size) values.resize(size=sz); if (is_zero()) sign=1; } else if (overflown < 65536){ values.resize(size+1); values[size++] = overflown; } else { values.resize(size+2); values[size++] = overflown % 65536; values[size++] = overflown >> 16; } } string bignum::to_s(int radix) const { if (is_zero()) return "0"; if (radix < 2 || 36 < radix) return "?"; stack<char> s; bignum tmp(*this); while(!tmp.is_zero()){ tmp /= radix; s.push(enc(tmp.remainder())); } stringstream ss; if (sign == -1) ss << "-"; while(!s.empty()){ ss << s.top(); s.pop(); } return ss.str(); } void bignum::set(string val, int radix){ set_zero(); if (radix < 2 || 36 < radix) return; default_radix_ = radix; int l=val.size(); int start=0, sg=1; if(val[0]=='-'){ sg = -1; start++; } else if(val[0]=='+') start++; for(int i=start,s=val.size();i<s;i++){ operator*=( radix ); operator+=( dec(val[i]) ); } normalize(); sign = sg; }
googletestつけとくよ
using namespace std; // #include "bignum.cc" #include <gtest/gtest.h> TEST(BignumTest, sdump) { bignum num; vector<int> v(1,0); num.set(1,v); EXPECT_EQ("+0<1>", num.sdump()); num.set(-1,v); EXPECT_EQ("+0<1>", num.sdump()); v[0]=1; num.set(1,v); EXPECT_EQ("+1<1>", num.sdump()); num.set(-1,v); EXPECT_EQ("-1<1>", num.sdump()); v[0]=65535; num.set(1,v); EXPECT_EQ("+FFFF<1>", num.sdump()); num.set(-1,v); EXPECT_EQ("-FFFF<1>", num.sdump()); v.resize(2); v[0]=v[1]=0; num.set(1,v); EXPECT_EQ("+0<1>", num.sdump()); num.set(-1,v); EXPECT_EQ("+0<1>", num.sdump()); v[0]=65535; v[1]=1; num.set(1,v); EXPECT_EQ("+1:FFFF<2>", num.sdump()); num.set(-1,v); EXPECT_EQ("-1:FFFF<2>", num.sdump()); v[1]=65535; num.set(1,v); EXPECT_EQ("+FFFF:FFFF<2>", num.sdump()); num.set(-1,v); EXPECT_EQ("-FFFF:FFFF<2>", num.sdump()); v.resize(3); v[2]=1; num.set(1,v); EXPECT_EQ("+1:FFFF:FFFF<3>", num.sdump()); num.set(-1,v); EXPECT_EQ("-1:FFFF:FFFF<3>", num.sdump()); v[2]=65535; num.set(1,v); EXPECT_EQ("+FFFF:FFFF:FFFF<3>", num.sdump()); num.set(-1,v); EXPECT_EQ("-FFFF:FFFF:FFFF<3>", num.sdump()); } TEST(BignumTest, to_i) { bignum num; EXPECT_EQ(0, num.to_i()); num=1; EXPECT_EQ(1, num.to_i()); num=2; EXPECT_EQ(2, num.to_i()); num=-1; EXPECT_EQ(-1, num.to_i()); num=-2; EXPECT_EQ(-2, num.to_i()); num=65535; EXPECT_EQ(65535, num.to_i()); num=-65535; EXPECT_EQ(-65535, num.to_i()); num=65536; EXPECT_EQ(65536, num.to_i()); num=-65536; EXPECT_EQ(-65536, num.to_i()); num=65537; EXPECT_EQ(65537, num.to_i()); num=-65537; EXPECT_EQ(-65537, num.to_i()); num=INT_MAX; EXPECT_EQ(INT_MAX, num.to_i()); num=-INT_MAX; EXPECT_EQ(-INT_MAX, num.to_i()); num=INT_MIN; EXPECT_EQ(INT_MIN, num.to_i()); // overflow case //... } TEST(BignumTest, ctor_from_signed_int) { bignum num; EXPECT_EQ(0, num.to_i()); EXPECT_EQ("+0<1>", num.sdump()); bignum num0(0); EXPECT_EQ(0, num0.to_i()); EXPECT_EQ("+0<1>", num0.sdump()); bignum num1(1); EXPECT_EQ(1, num1.to_i()); EXPECT_EQ("+1<1>", num1.sdump()); bignum num2(2); EXPECT_EQ(2, num2.to_i()); EXPECT_EQ("+2<1>", num2.sdump()); bignum num_1(-1); EXPECT_EQ(-1, num_1.to_i()); EXPECT_EQ("-1<1>", num_1.sdump()); bignum num_2(-2); EXPECT_EQ(-2, num_2.to_i()); EXPECT_EQ("-2<1>", num_2.sdump()); bignum numIMAX(INT_MAX); EXPECT_EQ(INT_MAX, numIMAX.to_i()); EXPECT_EQ("+7FFF:FFFF<2>", numIMAX.sdump()); bignum num_IMAX(-INT_MAX); EXPECT_EQ(-INT_MAX, num_IMAX.to_i()); EXPECT_EQ("-7FFF:FFFF<2>", num_IMAX.sdump()); bignum numIMIN(INT_MIN); EXPECT_EQ(INT_MIN, numIMIN.to_i()); EXPECT_EQ("-8000:0<2>", numIMIN.sdump()); } TEST(BignumTest, assign_signed_int) { bignum num; num=0; EXPECT_EQ(0, num.to_i()); EXPECT_EQ("+0<1>", num.sdump()); num=1; EXPECT_EQ(1, num.to_i()); EXPECT_EQ("+1<1>", num.sdump()); num=2; EXPECT_EQ(2, num.to_i()); EXPECT_EQ("+2<1>", num.sdump()); num=-1; EXPECT_EQ(-1, num.to_i()); EXPECT_EQ("-1<1>", num.sdump()); num=-2; EXPECT_EQ(-2, num.to_i()); EXPECT_EQ("-2<1>", num.sdump()); num=1000000; EXPECT_EQ(1000000, num.to_i()); EXPECT_EQ("+F:4240<2>", num.sdump()); num=-1000000; EXPECT_EQ(-1000000, num.to_i()); EXPECT_EQ("-F:4240<2>", num.sdump()); num=INT_MAX; EXPECT_EQ(INT_MAX, num.to_i()); EXPECT_EQ("+7FFF:FFFF<2>", num.sdump()); num=-INT_MAX; EXPECT_EQ(-INT_MAX, num.to_i()); EXPECT_EQ("-7FFF:FFFF<2>", num.sdump()); num=INT_MIN; EXPECT_EQ(INT_MIN, num.to_i()); EXPECT_EQ("-8000:0<2>", num.sdump()); } TEST(BignumTest, abs) { bignum num; EXPECT_EQ(0, num.abs().to_i()); EXPECT_EQ("+0<1>", num.abs().sdump()); num=1; EXPECT_EQ(1, num.abs().to_i()); EXPECT_EQ("+1<1>", num.abs().sdump()); num=2; EXPECT_EQ(2, num.abs().to_i()); EXPECT_EQ("+2<1>", num.abs().sdump()); num=-1; EXPECT_EQ(1, num.abs().to_i()); EXPECT_EQ("+1<1>", num.abs().sdump()); num=-2; EXPECT_EQ(2, num.abs().to_i()); EXPECT_EQ("+2<1>", num.abs().sdump()); num=INT_MAX; EXPECT_EQ(INT_MAX, num.abs().to_i()); EXPECT_EQ("+7FFF:FFFF<2>", num.abs().sdump()); num=-INT_MAX; EXPECT_EQ(INT_MAX, num.abs().to_i()); EXPECT_EQ("+7FFF:FFFF<2>", num.abs().sdump()); num=INT_MIN; EXPECT_EQ(INT_MIN, num.abs().to_i()); EXPECT_EQ("+8000:0<2>", num.abs().sdump()); vector<int> v(2,65535); num.set(1,v); EXPECT_EQ("+FFFF:FFFF<2>", num.abs().sdump()); num.set(-1,v); EXPECT_EQ("+FFFF:FFFF<2>", num.abs().sdump()); } TEST(BignumTest, minus) { bignum num; EXPECT_EQ(0, num.abs().to_i()); EXPECT_EQ("+0<1>", num.minus().sdump()); num=1; EXPECT_EQ(-1, num.minus().to_i()); EXPECT_EQ("-1<1>", num.minus().sdump()); num=2; EXPECT_EQ(-2, num.minus().to_i()); EXPECT_EQ("-2<1>", num.minus().sdump()); num=-1; EXPECT_EQ(1, num.minus().to_i()); EXPECT_EQ("+1<1>", num.minus().sdump()); num=-2; EXPECT_EQ(2, num.minus().to_i()); EXPECT_EQ("+2<1>", num.minus().sdump()); num=INT_MAX; EXPECT_EQ(-INT_MAX, num.minus().to_i()); EXPECT_EQ("-7FFF:FFFF<2>", num.minus().sdump()); num=-INT_MAX; EXPECT_EQ(INT_MAX, num.minus().to_i()); EXPECT_EQ("+7FFF:FFFF<2>", num.minus().sdump()); num=INT_MIN; EXPECT_EQ(INT_MAX+1, num.minus().to_i()); EXPECT_EQ("+8000:0<2>", num.minus().sdump()); vector<int> v(2,65535); num.set(1,v); EXPECT_EQ("-FFFF:FFFF<2>", num.minus().sdump()); num.set(-1,v); EXPECT_EQ("+FFFF:FFFF<2>", num.minus().sdump()); } TEST(BignumTest, to_s) { bignum num; EXPECT_EQ("0", num.to_s()); num=1; EXPECT_EQ("1", num.to_s()); num=2; EXPECT_EQ("2", num.to_s()); num=-1; EXPECT_EQ("-1", num.to_s()); num=-2; EXPECT_EQ("-2", num.to_s()); num=INT_MAX; EXPECT_EQ("2147483647", num.to_s()); num=-INT_MAX; EXPECT_EQ("-2147483647", num.to_s()); num=INT_MIN; EXPECT_EQ("-2147483648", num.to_s()); num=15; EXPECT_EQ("15", num.to_s()); EXPECT_EQ("1111", num.to_s(2)); EXPECT_EQ("F", num.to_s(16)); num=100; EXPECT_EQ("100", num.to_s()); EXPECT_EQ("64", num.to_s(16)); num=35; EXPECT_EQ("35", num.to_s()); EXPECT_EQ("100011", num.to_s(2)); EXPECT_EQ("23", num.to_s(16)); EXPECT_EQ("Z", num.to_s(36)); num=65537; EXPECT_EQ("65537", num.to_s()); EXPECT_EQ("10000000000000001", num.to_s(2)); EXPECT_EQ("10001", num.to_s(16)); num=1; for(int i=0;i<30;i++) num*=10; EXPECT_EQ("1000000000000000000000000000000", num.to_s()); num=1; for(int i=0;i<30;i++) num*=16; EXPECT_EQ("1000000000000000000000000000000", num.to_s(16)); } TEST(BignumTest, add_eq_signed_int) // testing operator += { bignum num; num=0; num+=2; EXPECT_EQ("+2<1>", num.sdump()); num=0; num+=-2; EXPECT_EQ("-2<1>", num.sdump()); num=1; num+=2; EXPECT_EQ("+3<1>", num.sdump()); num=1; num+=-2; EXPECT_EQ("-1<1>", num.sdump()); num=-1; num+=2; EXPECT_EQ("+1<1>", num.sdump()); num=-1; num+=-2; EXPECT_EQ("-3<1>", num.sdump()); num=50000; num+=50000; EXPECT_EQ(100000, num.to_i()); EXPECT_EQ("+1:86A0<2>", num.sdump()); num=50000; num+=-50000; EXPECT_EQ(0, num.to_i()); EXPECT_EQ("+0<1>", num.sdump()); num=-50000; num+=50000; EXPECT_EQ(0, num.to_i()); EXPECT_EQ("+0<1>", num.sdump()); num=-50000; num+=-50000; EXPECT_EQ(-100000, num.to_i()); EXPECT_EQ("-1:86A0<2>", num.sdump()); num=567890; num+=432100; EXPECT_EQ(999990, num.to_i()); EXPECT_EQ("+F:4236<2>", num.sdump()); num=567890; num+=-432100; EXPECT_EQ(135790, num.to_i()); EXPECT_EQ("+2:126E<2>", num.sdump()); num=-567890; num+=432100; EXPECT_EQ(-135790, num.to_i()); EXPECT_EQ("-2:126E<2>", num.sdump()); num=-567890; num+=-432100; EXPECT_EQ(-999990, num.to_i()); EXPECT_EQ("-F:4236<2>", num.sdump()); num=567890; num+=567889; EXPECT_EQ(1135779, num.to_i()); EXPECT_EQ("+11:54A3<2>", num.sdump()); num=567890; num+=-567889; EXPECT_EQ(1, num.to_i()); EXPECT_EQ("+1<1>", num.sdump()); num=-567890; num+=567889; EXPECT_EQ(-1, num.to_i()); EXPECT_EQ("-1<1>", num.sdump()); num=-567890; num+=-567889; EXPECT_EQ(-1135779, num.to_i()); EXPECT_EQ("-11:54A3<2>", num.sdump()); num=432100; num+=567890; EXPECT_EQ("+F:4236<2>", num.sdump()); num=432100; num+=-567890; EXPECT_EQ("-2:126E<2>", num.sdump()); num=-432100; num+=567890; EXPECT_EQ("+2:126E<2>", num.sdump()); num=-432100; num+=-567890; EXPECT_EQ("-F:4236<2>", num.sdump()); } TEST(BignumTest, sub_eq_signed_int) // testing operator -= { bignum num; num=0; num-=2; EXPECT_EQ("-2<1>", num.sdump()); num=0; num-=-2; EXPECT_EQ("+2<1>", num.sdump()); num=1; num-=2; EXPECT_EQ("-1<1>", num.sdump()); num=1; num-=-2; EXPECT_EQ("+3<1>", num.sdump()); num=-1; num-=2; EXPECT_EQ("-3<1>", num.sdump()); num=-1; num-=-2; EXPECT_EQ("+1<1>", num.sdump()); num=50000; num-=50000; EXPECT_EQ("+0<1>", num.sdump()); num=50000; num-=-50000; EXPECT_EQ("+1:86A0<2>", num.sdump()); num=-50000; num-=50000; EXPECT_EQ("-1:86A0<2>", num.sdump()); num=-50000; num-=-50000; EXPECT_EQ("+0<1>", num.sdump()); num=567890; num-=432100; EXPECT_EQ("+2:126E<2>", num.sdump()); num=567890; num-=-432100; EXPECT_EQ("+F:4236<2>", num.sdump()); num=-567890; num-=432100; EXPECT_EQ("-F:4236<2>", num.sdump()); num=-567890; num-=-432100; EXPECT_EQ("-2:126E<2>", num.sdump()); num=567890; num-=567889; EXPECT_EQ("+1<1>", num.sdump()); num=567890; num-=-567889; EXPECT_EQ("+11:54A3<2>", num.sdump()); num=-567890; num-=567889; EXPECT_EQ("-11:54A3<2>", num.sdump()); num=-567890; num-=-567889; EXPECT_EQ("-1<1>", num.sdump()); num=432100; num-=567890; EXPECT_EQ("-2:126E<2>", num.sdump()); num=432100; num-=-567890; EXPECT_EQ("+F:4236<2>", num.sdump()); num=-432100; num-=567890; EXPECT_EQ("-F:4236<2>", num.sdump()); num=-432100; num-=-567890; EXPECT_EQ("+2:126E<2>", num.sdump()); } TEST(BignumTest, mul_eq_signed_int) // testing operator *= { bignum num; num=0; num*=2; EXPECT_EQ("+0<1>", num.sdump()); num=0; num*=-2; EXPECT_EQ("+0<1>", num.sdump()); num=1; num*=2; EXPECT_EQ("+2<1>", num.sdump()); num=1; num*=-2; EXPECT_EQ("-2<1>", num.sdump()); num=-1; num*=2; EXPECT_EQ("-2<1>", num.sdump()); num=-1; num*=-2; EXPECT_EQ("+2<1>", num.sdump()); num=3; num*=5; EXPECT_EQ("+F<1>", num.sdump()); num=3; num*=-5; EXPECT_EQ("-F<1>", num.sdump()); num=-3; num*=5; EXPECT_EQ("-F<1>", num.sdump()); num=-3; num*=-5; EXPECT_EQ("+F<1>", num.sdump()); num=1000; num*=1000; EXPECT_EQ("+F:4240<2>", num.sdump()); num=1000; num*=-1000; EXPECT_EQ("-F:4240<2>", num.sdump()); num=-1000; num*=1000; EXPECT_EQ("-F:4240<2>", num.sdump()); num=-1000; num*=-1000; EXPECT_EQ("+F:4240<2>", num.sdump()); } TEST(BignumTest, div_eq_signed_int) // testing operator /= { bignum num; num=0; num/=2; EXPECT_EQ("+0<1>", num.sdump()); EXPECT_EQ(0, num.remainder()); num=0; num/=-2; EXPECT_EQ("+0<1>", num.sdump()); //EXPECT_EQ(0, num.remainder()); num=1; num/=2; EXPECT_EQ("+0<1>", num.sdump()); EXPECT_EQ(1, num.remainder()); num=1; num/=-2; EXPECT_EQ("+0<1>", num.sdump()); //EXPECT_EQ(1, num.remainder()); num=-1; num/=2; EXPECT_EQ("+0<1>", num.sdump()); //EXPECT_EQ(1, num.remainder()); num=-1; num/=-2; EXPECT_EQ("+0<1>", num.sdump()); //EXPECT_EQ(1, num.remainder()); num=13; num/=5; EXPECT_EQ("+2<1>", num.sdump()); EXPECT_EQ(3, num.remainder()); num=13; num/=-5; EXPECT_EQ("-2<1>", num.sdump()); //EXPECT_EQ(3, num.remainder()); num=-13; num/=5; EXPECT_EQ("-2<1>", num.sdump()); //EXPECT_EQ(3, num.remainder()); num=-13; num/=-5; EXPECT_EQ("+2<1>", num.sdump()); //EXPECT_EQ(3, num.remainder()); num=1000000; num/=1000; EXPECT_EQ("+3E8<1>", num.sdump()); EXPECT_EQ(0, num.remainder()); num=1000000; num/=-1000; EXPECT_EQ("-3E8<1>", num.sdump()); EXPECT_EQ(0, num.remainder()); num=-1000000; num/=1000; EXPECT_EQ("-3E8<1>", num.sdump()); EXPECT_EQ(0, num.remainder()); num=-1000000; num/=-1000; EXPECT_EQ("+3E8<1>", num.sdump()); EXPECT_EQ(0, num.remainder()); } TEST(BignumTest, add_eq_bignum) // += { bignum a, b; a=0, b=0; a+=b; EXPECT_EQ(0, a.to_i()); a=0, b=2; a+=b; EXPECT_EQ(2, a.to_i()); a=2, b=0; a+=b; EXPECT_EQ(2, a.to_i()); a=1, b=2; a+=b; EXPECT_EQ(3, a.to_i()); a=1, b=-2; a+=b; EXPECT_EQ(-1, a.to_i()); a=-1, b=2; a+=b; EXPECT_EQ(1, a.to_i()); a=-1, b=-2; a+=b; EXPECT_EQ(-3, a.to_i()); a=50000, b=50000; a+=b; EXPECT_EQ(100000, a.to_i()); a=50000, b=-50000; a+=b; EXPECT_EQ(0, a.to_i()); a=-50000, b=50000; a+=b; EXPECT_EQ(0, a.to_i()); a=-50000, b=-50000; a+=b; EXPECT_EQ(-100000, a.to_i()); a=567890, b=432100; a+=b; EXPECT_EQ(999990, a.to_i()); a=567890, b=-432100; a+=b; EXPECT_EQ(135790, a.to_i()); a=-567890, b=432100; a+=b; EXPECT_EQ(-135790, a.to_i()); a=-567890, b=-432100; a+=b; EXPECT_EQ(-999990, a.to_i()); a=567890, b=567889; a+=b; EXPECT_EQ(1135779, a.to_i()); a=567890, b=-567889; a+=b; EXPECT_EQ(1, a.to_i()); a=-567890, b=567889; a+=b; EXPECT_EQ(-1, a.to_i()); a=-567890, b=-567889; a+=b; EXPECT_EQ(-1135779, a.to_i()); a=432100, b=567890; a+=b; EXPECT_EQ(999990, a.to_i()); a=432100, b=-567890; a+=b; EXPECT_EQ(-135790, a.to_i()); a=-432100, b=567890; a+=b; EXPECT_EQ(135790, a.to_i()); a=-432100, b=-567890; a+=b; EXPECT_EQ(-999990, a.to_i()); } TEST(BignumTest, mul_eq_bignum) // testing operator *= { bignum a, b; a=0; b=0; a*=b; EXPECT_EQ(0, a.to_i()); a=0; b=2; a*=b; EXPECT_EQ(0, a.to_i()); a=2; b=0; a*=b; EXPECT_EQ(0, a.to_i()); a=1; b=1; a*=b; EXPECT_EQ(1, a.to_i()); a=1; b=2; a*=b; EXPECT_EQ(2, a.to_i()); a=2; b=1; a*=b; EXPECT_EQ(2, a.to_i()); a=2; b=2; a*=b; EXPECT_EQ(4, a.to_i()); a=3; b=-2; a*=b; EXPECT_EQ(-6, a.to_i()); a=-3; b=2; a*=b; EXPECT_EQ(-6, a.to_i()); a=-3; b=-2; a*=b; EXPECT_EQ(6, a.to_i()); a=10000; b=10000; a*=b; EXPECT_EQ(100000000, a.to_i()); a=100000000; b=100000000; a*=b; EXPECT_EQ("10000000000000000", a.to_s()); a=65535; b=65535; a*=b; EXPECT_EQ("FFFE0001", a.to_s(16)); a=65536; b=65536; a*=b; EXPECT_EQ("100000000", a.to_s(16)); } TEST(BignumTest, add) // + { bignum a, b; a=0, b=0; EXPECT_EQ(0, (a+b).to_i()); a=0, b=2; EXPECT_EQ(2, (a+b).to_i()); a=2, b=0; EXPECT_EQ(2, (a+b).to_i()); a=1, b=2; EXPECT_EQ(3, (a+b).to_i()); EXPECT_EQ(1, a.to_i()); EXPECT_EQ(2, b.to_i()); a=1, b=-2; EXPECT_EQ(-1, (a+b).to_i()); a=-1, b=2; EXPECT_EQ(1, (a+b).to_i()); a=-1, b=-2; EXPECT_EQ(-3, (a+b).to_i()); a=50000, b=50000; EXPECT_EQ(100000, (a+b).to_i()); a=50000, b=-50000; EXPECT_EQ(0, (a+b).to_i()); a=-50000, b=50000; EXPECT_EQ(0, (a+b).to_i()); a=-50000, b=-50000; EXPECT_EQ(-100000, (a+b).to_i()); a=567890, b=432100; EXPECT_EQ(999990, (a+b).to_i()); a=567890, b=-432100; EXPECT_EQ(135790, (a+b).to_i()); a=-567890, b=432100; EXPECT_EQ(-135790, (a+b).to_i()); a=-567890, b=-432100; EXPECT_EQ(-999990, (a+b).to_i()); a=567890, b=567889; EXPECT_EQ(1135779, (a+b).to_i()); a=567890, b=-567889; EXPECT_EQ(1, (a+b).to_i()); a=-567890, b=567889; EXPECT_EQ(-1, (a+b).to_i()); a=-567890, b=-567889; EXPECT_EQ(-1135779, (a+b).to_i()); a=432100, b=567890; EXPECT_EQ(999990, (a+b).to_i()); a=432100, b=-567890; EXPECT_EQ(-135790, (a+b).to_i()); a=-432100, b=567890; EXPECT_EQ(135790, (a+b).to_i()); a=-432100, b=-567890; EXPECT_EQ(-999990, (a+b).to_i()); } TEST(BignumTest, sub) // - { bignum a, b; a=0, b=0; EXPECT_EQ(0, (a-b).to_i()); a=0, b=2; EXPECT_EQ(-2, (a-b).to_i()); a=2, b=0; EXPECT_EQ(2, (a-b).to_i()); a=1, b=2; EXPECT_EQ(-1, (a-b).to_i()); EXPECT_EQ(1, a.to_i()); EXPECT_EQ(2, b.to_i()); a=1, b=-2; EXPECT_EQ(3, (a-b).to_i()); a=-1, b=2; EXPECT_EQ(-3, (a-b).to_i()); a=-1, b=-2; EXPECT_EQ(1, (a-b).to_i()); a=50000, b=50000; EXPECT_EQ(0, (a-b).to_i()); a=50000, b=-50000; EXPECT_EQ(100000, (a-b).to_i()); a=-50000, b=50000; EXPECT_EQ(-100000, (a-b).to_i()); a=-50000, b=-50000; EXPECT_EQ(0, (a-b).to_i()); a=567890, b=432100; EXPECT_EQ(135790, (a-b).to_i()); a=567890, b=-432100; EXPECT_EQ(999990, (a-b).to_i()); a=-567890, b=432100; EXPECT_EQ(-999990, (a-b).to_i()); a=-567890, b=-432100; EXPECT_EQ(-135790, (a-b).to_i()); a=567890, b=567889; EXPECT_EQ(1, (a-b).to_i()); a=567890, b=-567889; EXPECT_EQ(1135779, (a-b).to_i()); a=-567890, b=567889; EXPECT_EQ(-1135779, (a-b).to_i()); a=-567890, b=-567889; EXPECT_EQ(-1, (a-b).to_i()); a=432100, b=567890; EXPECT_EQ(-135790, (a-b).to_i()); a=432100, b=-567890; EXPECT_EQ(999990, (a-b).to_i()); a=-432100, b=567890; EXPECT_EQ(-999990, (a-b).to_i()); a=-432100, b=-567890; EXPECT_EQ(135790, (a-b).to_i()); a.set("H",36); b.set("H",36); EXPECT_EQ("0", (a-b).to_s(36)); a.set("HZ",36); b.set("HE",36); EXPECT_EQ("L", (a-b).to_s(36)); a.set("HZL",36); b.set("HEL",36); EXPECT_EQ("L0", (a-b).to_s(36)); a.set("HZLO",36); b.set("HELO",36); EXPECT_EQ("L00", (a-b).to_s(36)); a.set("HZLLO",36); b.set("HELLO",36); EXPECT_EQ("L000", (a-b).to_s(36)); } TEST(BignumTest, mul) // * { bignum a, b; a=0; b=0; EXPECT_EQ(0, (a*b).to_i()); a=0; b=2; EXPECT_EQ(0, (a*b).to_i()); a=2; b=0; EXPECT_EQ(0, (a*b).to_i()); a=1; b=1; EXPECT_EQ(1, (a*b).to_i()); a=1; b=2; EXPECT_EQ(2, (a*b).to_i()); a=2; b=1; EXPECT_EQ(2, (a*b).to_i()); a=2; b=2; EXPECT_EQ(4, (a*b).to_i()); a=3; b=-2; EXPECT_EQ(-6, (a*b).to_i()); a=-3; b=2; EXPECT_EQ(-6, (a*b).to_i()); a=-3; b=-2; EXPECT_EQ(6, (a*b).to_i()); a=10000; b=10000; EXPECT_EQ(100000000, (a*b).to_i()); a=100000000; b=100000000; EXPECT_EQ("10000000000000000", (a*b).to_s()); a=65535; b=65535; EXPECT_EQ("FFFE0001", (a*b).to_s(16)); a=65536; b=65536; EXPECT_EQ("100000000", (a*b).to_s(16)); } TEST(BignumTest, comparison) // == != < <= > >= { bignum a, b; a= 0, b= 0; EXPECT_TRUE(a==b); EXPECT_FALSE(a!=b); EXPECT_FALSE(a>b); EXPECT_TRUE(a>=b); EXPECT_FALSE(a<b); EXPECT_TRUE(a<=b); a= 1, b= 1; EXPECT_TRUE(a==b); EXPECT_FALSE(a!=b); EXPECT_FALSE(a>b); EXPECT_TRUE(a>=b); EXPECT_FALSE(a<b); EXPECT_TRUE(a<=b); a=-1, b=-1; EXPECT_TRUE(a==b); EXPECT_FALSE(a!=b); EXPECT_FALSE(a>b); EXPECT_TRUE(a>=b); EXPECT_FALSE(a<b); EXPECT_TRUE(a<=b); a= 1, b=-1; EXPECT_FALSE(a==b); EXPECT_TRUE(a!=b); EXPECT_TRUE(a>b); EXPECT_TRUE(a>=b); EXPECT_FALSE(a<b); EXPECT_FALSE(a<=b); a=-1, b= 1; EXPECT_FALSE(a==b); EXPECT_TRUE(a!=b); EXPECT_FALSE(a>b); EXPECT_FALSE(a>=b); EXPECT_TRUE(a<b); EXPECT_TRUE(a<=b); a=1, b=0; EXPECT_FALSE(a==b); EXPECT_TRUE(a!=b); EXPECT_TRUE(a>b); EXPECT_TRUE(a>=b); EXPECT_FALSE(a<b); EXPECT_FALSE(a<=b); a=10000000, b=0; EXPECT_FALSE(a==b); EXPECT_TRUE(a!=b); EXPECT_TRUE(a>b); EXPECT_TRUE(a>=b); EXPECT_FALSE(a<b); EXPECT_FALSE(a<=b); } TEST(BignumTest, assign_by_string) { bignum num; num.set(""); EXPECT_EQ(0, num.to_i()); num.set("0"); EXPECT_EQ(0, num.to_i()); num.set("1"); EXPECT_EQ(1, num.to_i()); num.set("-1"); EXPECT_EQ(-1, num.to_i()); num.set("111"); EXPECT_EQ(111, num.to_i()); num.set("111",2); EXPECT_EQ(7, num.to_i()); num.set("-111"); EXPECT_EQ(-111, num.to_i()); num.set("-111",2); EXPECT_EQ(-7, num.to_i()); num.set("12"); EXPECT_EQ(12, num.to_i()); num.set("-12"); EXPECT_EQ(-12, num.to_i()); num.set("12",16); EXPECT_EQ(18, num.to_i()); num.set("-12",16); EXPECT_EQ(-18, num.to_i()); num.set("ZZ",36); EXPECT_EQ(1295, num.to_i()); num.set("-ZZ",36); EXPECT_EQ(-1295, num.to_i()); } int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
SRM434 Div1 Medium: HexatridecimalSum
時間切れから6分後に出来たやつでそのままSysTest通った件(無念)
typedef long long ll; typedef vector<int> vi; typedef vector<vector<int> > vvi; typedef vector<string> vs; typedef vector<long long> vll; #define sz(a) int((a).size()) #define pb push_back #define all(c) (c).begin(),(c).end() #define mset(arr,val) memset(arr,val,sizeof(arr)) #define tr(c,i) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++) #define rep(var,n) for(int var=0;var<(n);var++) #define forr(var,from,to) for(int var=(from);var<=(to);var++) #define found(s,e) ((s).find(e)!=(s).end()) #define remove_(c,val) (c).erase(remove((c).begin(),(c).end(),(val)),(c).end()) #define lastc(str) (*((str).end()-1)) class HexatridecimalSum { int de(int c){ if('0'<=c && c<='9') return c-'0'; else return 10+(c-'A'); } int en(int c){ if (c<10) return '0'+c; else return 'A'+(c-10); } public: string maximizeSum(vector<string> numbers, int k) { vvi m(52); rep(i,52) m[i].resize(0); tr(numbers,it){ string ns=*it; int l=sz(ns); rep(i,l) m[i].pb(de(ns[l-i-1])); } int maxk = 0; rep(i,52){ if(sz(m[i])>0) maxk=i; sort(all(m[i])); } vvi di(36),id(36); rep(i,36) { di[i].resize(maxk+3); id[i].resize(maxk+3); rep(j,maxk+3) di[i][j] = id[i][j] = 0; } vi sum(maxk+3,0); for(int i=maxk;i>=0;i--){ tr(m[i],it) { int c = *it; di[c][i] += (35-c); sum[maxk+2-i] += c; } } rep(c,36) { rep(i,maxk+2){ if(di[c][i] >= 36) { di[c][i+1] += di[c][i]/36; di[c][i] %= 36; } } } rep(c,36){ rep(i,maxk+3){ id[c][maxk+2-i] = di[c][i]; } } sort(all(id)); reverse(all(id)); rep(i,k){ rep(j,maxk+3){ sum[j] += id[i][j]; } } for(int i=maxk+2;i>0;i--){ if(sum[i] >= 36) { sum[i-1] += sum[i]/36; sum[i] %= 36; } } bool left=true; stringstream ss; rep(i,maxk+3){ if (left && sum[i]==0) continue; left=false; ss << (char)en(sum[i]); } return ss.str(); } };
SRM434 Div1 Easy: FindingSquareInTable
#define sz(a) int((a).size()) #define pb push_back #define all(c) (c).begin(),(c).end() #define tr(c,i) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++) #define rep(var,n) for(int var=0;var<(n);var++) #define found(s,e) ((s).find(e)!=(s).end()) class FindingSquareInTable { set<int> psqs; bool psq(int n){ return found(psqs,n) ? true : false; } public: int findMaximalSquare(vector<string> table) { for(int i=0;i<=31622; i++) psqs.insert(i*i); int maxn = -1; int h=sz(table), w=sz(table[0]); vector<vector<int> > t(h); rep(i,h) { t[i].resize(w); rep(j,w) t[i][j] = table[i][j] - '0'; } rep(j0,h) rep(i0,w){ for(int sy=-(h-1);sy<=h-1;sy++){ for(int sx=-(w-1);sx<=w-1;sx++){ int j=j0, i=i0; int n=t[j][i]; if(sx==0 && sy==0) goto jm; while(true){ i+=sx; j+=sy; if (i < 0 || w <= i || j < 0 || h <= j) break; n = n*10 + t[j][i]; if (psq(n)) maxn = max(maxn,n); // ←この1行 } jm: if (psq(n)) maxn = max(maxn,n); } } } return maxn; } };
SRM434
|02.08.2009
1問submit、1問沈没。0点><
DIV | level | 問題名 | 競技中 | 後で | System Test | 通過率 | 備考 |
---|---|---|---|---|---|---|---|
1 | 250 | FindingSquareInTable | 撃沈 | ◎ | 0.0 | ||
1 | 500 | HexatridecimalSum | 間に合わず | ◎ | |||
1 | 1000 | - | - |
250点問題: FindingSquareInTable
- 撃沈
- テーブルの途中で数字列が終わってもいい
- そこが撃沈ポイント
500点問題: HexatridecimalSum
- 6分ほど足りない。
- →6分余分にかけて解いたやつがすんなりSysTestパスした。くやしい
- Bignum実装しておくべし。あるいはJava
1000点問題:
- 開かず。
0点。447/684位... レーティングまた落ちた
1487→1405
順調な下がりっぷり
全く歯が立たないわけではないので引き続き頑張る
SRM356 Div1 Easy: AverageProblem
- 丸め誤差に泣く問題。再投稿×2
class AverageProblem { public: int numberOfParticipants(vector<string> marks) { set<int> s; tr(marks,it){ vector<string> m_ = split(*it); tr(m_,jt) s.insert((int)(1000 * atof(jt->c_str()) + 0.5)); } for(int ps=1;;ps++){ set<int> s_; double u = 1000.0 / ps; for(int i=0;i<=ps*10;i++) s_.insert((int)(u*i+0.0000001)); tr(s,it) if (!found(s_,*it)) goto next; return ps; next:; } } };
SRM357 Div1 Easy: Hotel
久しぶりに練習。201.66points。(14.65min) ... 時間かかりすぎ
- DPですね。下(0)から行きます
#define sz(a) int((a).size()) #define all(c) (c).begin(),(c).end() #define tr(c,i) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++) #define rep(var,n) for(int var=0;var<(n);var++) class Hotel { public: int marketCost(int minCustomers, vector<int> customers, vector<int> cost) { int n=sz(customers); int maxc = minCustomers + *max_element(all(customers)); vector<int> v(maxc+1, INT_MAX); v[0] = 0; rep(mc,minCustomers) { if (v[mc] == INT_MAX) continue; rep(i,n){ int c=customers[i], ct=cost[i]; v[mc+c] = min(v[mc+c],v[mc]+ct); } } int ct = INT_MAX; for(int mc=minCustomers; mc<=maxc; mc++) ct = min(ct,v[mc]); return ct; } };