Cod sursa(job #246420)

Utilizator savimSerban Andrei Stan savim Data 20 ianuarie 2009 20:45:55
Problema Numere 2 Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.66 kb
#include <stdio.h>
#include <string.h>

#define MAX_L 35
#define len 30
#define baz 10000
#define bazl 4

char c[110];
int P[MAX_L], inf[MAX_L], sup[MAX_L], mid[MAX_L], rez[MAX_L], sol[MAX_L], v[MAX_L], inter[MAX_L];
int n, m, sol_ok, wrong;

void cit() {
	freopen("numere2.in", "r", stdin);
	freopen("numere2.out", "w", stdout);
	
	scanf("%s", c);
	n = strlen(c);
	
	int i = n - 1; m = len;
	while (i >= 0) {
		int k = 0;
		for (int j = bazl - 1; j >= 0; j--)
			if (i - j >= 0) 
				k = k * 10 + c[i - j] - '0';
		P[m--] = k;
		i -= bazl;
	}
}

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

int comp(int inf[MAX_L], int sup[MAX_L]) {
	for (int 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 (int i = 1; i <= len; i++)
		mid[i] = inf[i] + sup[i];
	for (int i = len; i >= 1; i--) {
		mid[i - 1] += mid[i] / baz;
		mid[i] %= baz;
	}
	
	int k = 0, ind = 0;
	while (k * baz + mid[ind] < 2 && ind <= len)
		k = k * baz + mid[ind++];
	
	for (int i = ind; i <= len; i++) {
		k = k * baz + mid[i];
		mid[i] = k / 2;
		k = k % 2;
	}
	mid[ind - 1] = 0;
}

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

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

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


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

void caut_binar(int B) {
	//calculez sup, inf il am de la pasul anterior
	for (int i = 1; i <= len; i++) sup[i] = P[i];
	sup[len]++;
	for (int 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 (int i = 0; i <= len; i++) rez[i] = 0;
		wrong = 0; rez[len] = 1;
		calc_rez(B);
		
		int 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 (int B = 1; B >= 1; B--) {
		//caut binar numarul A
		caut_binar(B);
		
		if (sol_ok) return;
	}
}

void write() {
	int poz = 0;
	for (int i = 1; i <= len; i++)
		if (sol[i] != 0) {
			poz = i;
			break;
		}
	
	printf("%d", sol[poz]);
	for (int i = poz + 1; i <= len; i++) {
		int cop = sol[i];
		
		if (cop != 0)
		while (cop * 10 < baz) {
			printf("0");
			cop *= 10;
		}
		else 
			for (int j = 0; j < bazl; j++)
				printf("0");
		
		printf("%d", sol[i]);
	}
	printf("\n");
	printf("%d\n", sol[0]);
}

int main() {

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