Cod sursa(job #246372)

Utilizator savimSerban Andrei Stan savim Data 20 ianuarie 2009 19:29:34
Problema Numere 2 Scor 15
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.31 kb
#include <stdio.h>
#include <string.h>

#define MAX_L 110
#define len 100
#define si short int
#define baz 10

char c[MAX_L];
si P[MAX_L], inf[MAX_L], sup[MAX_L], mid[MAX_L], rez[MAX_L], sol[MAX_L], v[MAX_L], sier[MAX_L];
si n, sol_ok, wrong;

void cit() {
	freopen("numere2.in", "r", stdin);
	freopen("numere2.out", "w", stdout);
	
	scanf("%s", c);
	n = strlen(c);
	
	for (si i = len - n + 1; i <= len; i++)
		P[i] = c[i - len + n - 1] - '0';
}

void inf_mid() {
	for (si i = 1; i <= len; i++) mid[i] = inf[i];
	mid[len]++;
	for (si i = len; i>= 1; i--) {
		mid[i - 1] += mid[i] / baz;
		mid[i] %= baz;
	}
}

si comp(si inf[MAX_L], si sup[MAX_L]) {
	for (si i = 0; i <= len; i++) {
		if (inf[i] < sup[i]) return -1;
		if (inf[i] > sup[i]) return 1;
	}
	return 0;
}

void calc_mid() {
	//calculez mijlocul = (inf + sup) / 2
	
	for (si i = 1; i <= len; i++)
		mid[i] = inf[i] + sup[i];
	for (si i = len; i >= 1; i--) {
		mid[i - 1] += mid[i] / baz;
		mid[i] %= baz;
	}
	
	si k = 0, ind = 0;
	while (k * baz + mid[ind] < 2 && ind <= len)
		k = k * baz + mid[ind++];
	
	for (si i = ind; i <= len; i++) {
		k = k * baz + mid[i];
		mid[i] = k / 2;
		k = k % 2;
	}
	mid[ind - 1] = 0;
}

void cop(si a[MAX_L], si b[MAX_L]) {
	for (si i = 0; i <= len; i++)
		a[i] = b[i];
}

void get_sol(si B) {
	for (si i = 1; i <= len; i++)
		sol[i] = mid[i];
	sol[0] = B;
	sol_ok = 1;
}

void inmultesc(si rez[MAX_L], si b[MAX_L]) {
	si poz1 = 0, poz2 = 0;
	
	for (si i = 1; i <= len; i++)
		if (rez[i] != 0) {
			poz1 = i;
			break;
		}
	for (si i = 1; i <= len; i++)
		if (b[i] != 0) {
			poz2 = i;
			break;
		}
	
	if ((len - poz1 + 1) * (len - poz2 + 1) >= len) {
		wrong = 1;
		return;
	}
		
	for (si i = 1; i <= len; i++) sier[i] = 0;
	si x = len;
	for (si i = len; i >= poz1; i--) {
		for (si j = 0; j <= len; j++) v[j] = 0;
		for (si j = len; j >= poz2; j--) {
			v[j] += b[j] * rez[i];
			v[j - 1] += v[j] / baz;
			v[j] %= baz;
		}
		
		si k = len;
		for (si j = x; j >= 1; j--) {
			sier[j] += v[k--];
			sier[j - 1] += sier[j] / baz;
			sier[j] %= baz;
		}
		x--;
	}
	
	cop(rez, sier);
}


void calc_rez(si put) {
	if (put == 0 || wrong) return;
	
	calc_rez(put / 2);
	inmultesc(rez, rez);
	
	if (put % 2 == 1) inmultesc(rez, mid);
}

void caut_binar(si B) {
	//calculez sup, inf il am de la pasul anterior
	for (si i = 1; i <= len; i++) sup[i] = P[i];
	sup[len]++;
	for (si i = len; i >= 1; i--) {
		sup[i - 1] += sup[i] / baz;
		sup[i] %= baz;
	}
	
	inf_mid();
	while (comp(mid, sup) < 0) {
		calc_mid();
		
		//calculez mid ^ B
		for (si i = 0; i <= len; i++) rez[i] = 0;
		wrong = 0; rez[len] = 1;
		calc_rez(B);
		
		si ok = comp(rez, P);
		if (wrong) ok = 1;
		if (ok < 0) cop(inf, mid);
			else if (ok > 0) cop(sup, mid);
		         else {
					get_sol(B);
					return;
				 }
		
		inf_mid();
	}
}

void solve() {
	//aleg puterea B
	for (si B = 400; B >= 1; B--) {
		//caut binar numarul A
		caut_binar(B);
		
		if (sol_ok) return;
	}
}

void write() {
	si poz = 0;
	for (si i = 1; i <= len; i++)
		if (sol[i] != 0) {
			poz = i;
			break;
		}
	
	for (si i = poz; i <= len; i++)
		printf("%d", sol[i]);
	printf("\n");
	printf("%d\n", sol[0]);
}

int main() {

	cit();
	solve();
	write();
	
	return 0;
}