Skip to content

Commit

Permalink
2 problems from recruit coders, BigInt library way faster
Browse files Browse the repository at this point in the history
  • Loading branch information
ajmarin committed Jul 13, 2011
1 parent 6672595 commit fdd3a12
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 176 deletions.
245 changes: 69 additions & 176 deletions lib/bigint.cpp
Expand Up @@ -3,201 +3,94 @@
#include <cmath>
#include <cstdio>
#include <string>
#define FOR(i,n) for(int i = 0; i < n; ++i)
using namespace std;
#define BASE 1000
#define DIGITS 1000
#define LOG10BASE 3
struct BigInt {
string n;
BigInt(string num = "0"){
n = num;
reverse(n.begin(), n.end());
}
BigInt(long long num){
n = num ? "" : "0";
while(num) n += num % 10 + '0', num /= 10;
}
BigInt operator +(BigInt b){
BigInt r;
r.n = n;
int c, i, l1 = r.n.size(), l2 = b.n.size();
for(i = l1; i < l2; ++i) r.n += '0';
for(i = l2; i < l1; ++i) b.n += '0';
for(c = i = 0; i < l1 || i < l2; ++i){
r.n[i] = ((c = r.n[i] - '0' + b.n[i] - '0' + c) % 10) + '0';
c /= 10;
int num[DIGITS];
void clear(){ FOR(i, DIGITS) num[i] = 0; }
void carry(){
int c = 0;
FOR(i, DIGITS){
c = (num[i] += c) / BASE;
num[i] %= BASE;
}
if(c) r.n += c + '0', ++i;
b.n = b.n.substr(0, l2);
return r;
}
BigInt operator +=(BigInt b){
return *this = *this + b;
}
BigInt operator +(long long a){
return *this + BigInt(a);
}
BigInt operator +=(long long a){
return *this = *this + BigInt(a);
}
BigInt operator -(BigInt b){
BigInt r;
if(*this == b) return BigInt("0");
assert(*this >= b);
int i, l1 = n.size(), l2 = b.n.size();
for(i = 0; i < l2; ++i) b.n[i] = '9' - b.n[i] + '0';
for(i = l2; i < l1; ++i) b.n += '9';
r = *this + b;
l1 = r.n.size();
r.n[l1 - 1]--;
r += 1;
r.trim();
for(i = 0; i < l2; ++i) b.n[i] = '9' - b.n[i] + '0';
b.n = b.n.substr(0, l2);
return r;
}
BigInt operator -=(BigInt b){
return *this = *this - b;
}
BigInt operator -(long long a){
return *this - BigInt(a);
}
BigInt operator -=(long long a){
return *this = *this - BigInt(a);
}
BigInt operator *(BigInt b){
BigInt r, s;
int c, i, j, l1 = n.size(), l2 = b.n.size();
for(i = 0; i < l1; ++i){
s.n = string(i, '0');
for(c = j = 0; j < l2; ++j){
s.n += (c = (n[i] - '0') * (b.n[j] - '0') + c) % 10 + '0';
c /= 10;
}
while(c) s.n += ((c % 10) + '0'), c /= 10;
r = r + s;
int get_last(){ int i; for(i = DIGITS; i-- && !num[i]; ); return i + 1; }
void show(){
int i = get_last(), j, k;
char c[LOG10BASE + 1];
c[LOG10BASE] = 0;
printf("%d", num[--i]);
while(i--){
for(j = LOG10BASE, k = num[i]; j--; c[j] = k%10 + '0', k /= 10);
printf("%s", c);
}
r.trim();
return r;
}
BigInt operator *=(BigInt b){
return *this = *this * b;
}
BigInt operator *(long long a){
return *this * BigInt(a);
}
BigInt operator *=(long long a){
return *this = *this * BigInt(a);
}
BigInt operator >>(int x){
BigInt r = *this;
reverse(r.n.begin(), r.n.end());
for(int i = 0; i < x; ++i){
string result = "";
int d = 0, sz = r.n.size();
for(int i = 0; i < sz; ++i){
d = d * 10 + r.n[i] - '0';
result += (d >> 1) + '0';
d &= 1;
puts("");
}
BigInt(int v = 0){ clear(); num[0] = v; carry(); }
BigInt(char *v){
char *last = v;
int mult, pos = 0, z;
clear();
while(*last) ++last; --last;
while(last >= v){
mult = 1; z = 0;
FOR(i, LOG10BASE){
z = mult * (*last - '0') + z;
mult *= 10;
if(--last < v) break;
}
r.n = result;
num[pos++] = z;
}
reverse(r.n.begin(), r.n.end());
r.trim();
return r;
}
BigInt sqroot(){
string num = n; int l = n.size();
reverse(num.begin(), num.end());
BigInt r, rem, x(num.substr(0, 2 - (l & 1)));
int f = l & 1 ? x.n[0] - '0' : 10 * (x.n[1] - '0') + (x.n[0] - '0');
f = (int)sqrt(f);
r = BigInt(f);
rem = x - f * f;
for(int i = 2 - (l & 1), d; i < l; i += 2){
BigInt down = r * 20;
rem = rem * 100 + num.substr(i, 2);
rem.trim();
for(d = 1; d < 10 && ((down + d) * d) <= rem; ++d);
r.n = (char)(--d + '0') + r.n;
rem = rem - (down + d) * d;
}
BigInt(string v){ BigInt(v.c_str()); }
BigInt(BigInt* b){ FOR(i, DIGITS) num[i] = b->num[i]; }
BigInt operator+(BigInt b){
BigInt r = this;
FOR(i, DIGITS) r.num[i] += b.num[i];
r.carry();
return r;
}
bool operator ==(BigInt b){
return mycmp(b) == 0;
}
bool operator !=(BigInt b){
return mycmp(b) != 0;
}
bool operator >(BigInt b){
return mycmp(b) > 0;
}
bool operator >=(BigInt b){
return mycmp(b) >= 0;
}
bool operator <(BigInt b){
return mycmp(b) < 0;
}
bool operator <=(BigInt b){
return mycmp(b) <= 0;
}
bool operator ==(long long a){
return *this == BigInt(a);
}
bool operator !=(long long a){
return *this != BigInt(a);
}
bool operator >(long long a){
return *this > BigInt(a);
}
bool operator >=(long long a){
return *this >= BigInt(a);
}
bool operator <(long long a){
return *this < BigInt(a);
}
bool operator <=(long long a){
return *this <= BigInt(a);
}
void trim(){
int i; for(i = n.size(); --i && n[i] == '0'; )
n = n.substr(0, i);
}
int mycmp(BigInt b){
int i, l1 = n.size(), l2 = b.n.size();
if(l1 != l2) return (l1 > l2) - (l1 < l2);
for(i = l1; i-- && n[i] == b.n[i]; );
if(i == -1) return 0;
return (n[i] > b.n[i]) - (n[i] < b.n[i]);
}
void show(){
printf("%s\n", to_string().c_str());
}
string to_string(){
string s = n;
reverse(s.begin(), s.end());
return s;
BigInt operator*(BigInt b){
BigInt r;
int lim_i = get_last(), lim_j = b.get_last();
FOR(i, lim_i) FOR(j, lim_j) r.num[i+j] += num[i] * b.num[j];
r.carry();
return r;
}
BigInt operator+=(BigInt b){ return *this = *this + b; }
BigInt operator*=(BigInt b){ return *this = *this * b; }
int compare(const BigInt b){
int lim_i = get_last(), lim_j = get_last();
if(lim_i != lim_j) return (lim_i > lim_j) - (lim_i < lim_j);
for(int x = lim_i; x--; )
if(num[x] != b.num[x]) return (num[x] > b.num[x]) - (num[x] < b.num[x]);
return 0;
}
bool operator>(BigInt b){ return compare(b) == 1; }
bool operator>=(BigInt b){ return compare(b) > -1; }
bool operator==(BigInt b){ return compare(b) == 0; }
bool operator<(BigInt b){ return compare(b) == -1; }
bool operator<=(BigInt b){ return compare(b) < 1; }
bool operator!=(BigInt b){ return compare(b) != 0; }
};

int main(void){
BigInt r = "12345678987654321";
assert(r * 7 == "86419752913580247");
assert(BigInt(69) > BigInt(52));
assert(BigInt(1048576) >> 20 == 1);
assert(BigInt(63) >> 5 == 1);
assert(BigInt(1) - 1 == 0);
assert(BigInt(81).sqroot() == 9);
assert(BigInt("4567486383288161726959913764561").sqroot() == 2137167841627831LL);
assert(BigInt(15241578750190521LL).sqroot() == 123456789);
assert(BigInt(10000).sqroot() == 100);
assert(BigInt(873) > BigInt(218));
assert(BigInt(159) < BigInt(951));
assert(BigInt(873) - BigInt(218) == 655);
assert(BigInt(1000) - BigInt(2) == 998);
assert(BigInt(5) * BigInt(2) == BigInt(10));
assert(BigInt(777) * BigInt(3333) == BigInt(2589741));
assert(BigInt(1LL<<62) + BigInt(1LL<<62) == BigInt("9223372036854775808"));
assert(BigInt(1LL<<60) + BigInt(1LL<<60) == 1LL<<61);
assert(BigInt(1LL<<50) * BigInt(1LL<<10) == BigInt(1LL<<60));
assert(BigInt("4611686018427387904") + BigInt("4611686018427387904") == BigInt("9223372036854775808"));
assert(BigInt("1152921504606846976") + BigInt("1152921504606846976") == "2305843009213693952");
assert(BigInt("1125899906842624") * BigInt(1<<10) == BigInt("1152921504606846976"));
assert(BigInt(2) > BigInt("1"));
assert(BigInt(1LL<<30) >= BigInt(1LL<<30));
assert(BigInt(1<<30) >= BigInt(1<<30));
assert(BigInt("123456789999999999998") < BigInt("123456789999999999999"));
assert(BigInt("123456789999999999999") <= BigInt("123456789999999999999"));
assert(BigInt("1723") < 88884);
Expand All @@ -206,4 +99,4 @@ int main(void){
assert(BigInt(130) <= 130);
printf("TEST SUCEEDED\n");
return 0;
}
}
66 changes: 66 additions & 0 deletions rc/cbigint.c
@@ -0,0 +1,66 @@
#include <stdio.h>
#define FOR(i,n) for(i = 0; i < n; ++i)
#define DIGITS 10000
#define BASE 1000
#define BP10 3

int num1[DIGITS], num2[DIGITS];
int res[DIGITS];
int i, j;
int get_last(int* a){
int i;
for(i = DIGITS; i-- && !a[i]; );
return i + 1 + (i == -1);
}
void carry(int* a){
int c = 0;
FOR(i, DIGITS){
c = (a[i] += c) / BASE;
a[i] %= BASE;
}
}
void add(int* a, int *b){
FOR(i, DIGITS) a[i] += b[i];
carry(a);
}
void mul(int *a, int *b){
int lim_i = get_last(a), lim_j = get_last(b);
FOR(i, lim_i) FOR(j, lim_j) res[i+j] += a[i] * b[j];
carry(res);
}
void read(char *n, int *d){
char *last = n;
int j = 0, base = 1, x;
while(*last) ++last; --last;
while(last >= n){
base = 1, x = 0;
FOR(i, 3){
x += (*last-- - '0') * base;
base *= 10;
if(last < n) break;
}
d[j++] = x;
}
}
void show(int *n){
i = get_last(n);
printf("%d", n[--i]);
while(i--) printf("%03d", n[i]);
puts("");
}
char n1[DIGITS], n2[DIGITS];
int main(void){
int t; scanf("%d", &t);
while(t--){
for(i = 0; i < DIGITS; ++i) num1[i] = num2[i] = res[i] = 0;
scanf("%s %s", n1, n2);
read(n1, num1);
read(n2, num2);
//show(num1); puts("*"); show(num2);
mul(num1, num2);
show(res);
//puts("-------------------");
}
return 0;
}

42 changes: 42 additions & 0 deletions rc/segsieve.cpp
@@ -0,0 +1,42 @@
#include <cmath>
#include <cstdio>
#define FOR(i,n) for(int i = 0; i < n; ++i)
#define FORI(i,f,n) for(int i = f; i < n; ++i)
#define FORS(i,f,n,s) for(int i = f; i < n; i += s)
#define MAX(a,b) ((a) > (b) ? (a) : (b))
const int MAXP = 1<<16, ROOT = 1<<8;
int pl[MAXP/10], pc = 0;
bool prime[MAXP];
bool segprime[1000048];
int main(void){
FOR(i, MAXP) prime[i] = i > 1;
FORS(i, 4, MAXP, 2) prime[i] = false;
FORS(i, 3, ROOT, 2) if(prime[i]){
FORS(j, i*i, MAXP, i<<1) prime[j] = false;
}
FOR(i, MAXP) if(prime[i]) pl[pc++] = i;// printf("%d\n", i);
int t; scanf("%d", &t);
while(t--){
int a, b, first, from, limit, range, step, to;
scanf("%d %d", &from, &to);
range = to - from + 1;
limit = int(floor(sqrt(to)));
FOR(i, range) segprime[i] = true;
if(from <= 2 && to >= 2) puts("2");
FORI(i, 1, pc){
if(pl[i] > limit) break;
a = pl[i] * pl[i];
b = ((from + pl[i] - 1)/ pl[i]) * pl[i];
if(!(b & 1)) b += pl[i];
first = MAX(a, b);
step = pl[i] << 1;
FORS(j, first - from, range, step) segprime[j] = false;
//printf("%d isnt prime due to %d\n", j + from, pl[i]);
}
FORS(i, !(from & 1), range, 2) if(segprime[i]) printf("%d\n", i + from);
}

return 0;
}


Empty file modified timus/T1014.cpp 100755 → 100644
Empty file.

0 comments on commit fdd3a12

Please sign in to comment.