Cod sursa(job #17782)

Utilizator m_dersidanDersidan Mihai m_dersidan Data 16 februarie 2007 21:08:56
Problema Numere 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.99 kb
# include <stdio.h>
# include <string.h>

# define  _fin  "numere2.in"
# define  _fout "numere2.out"

# define  maxd  402

int p[maxd], a[3*maxd], b;


void readf()
{
	char buf[2*maxd];
	FILE *fin=fopen(_fin, "r");
	fgets(buf, maxd, fin);
	
	int i=0, to=strlen(buf)-1;
	for(i=to-1;i>=0; i--) p[++p[0]] = buf[i]-0x30;
}
/*
void mul(int a[], int b)
{
	int i=1, t=0;
	for (; i<=a[0] || t; i++, t/= 10)
		a[i] = ( t+=a[i]*b ) % 10;
	
	a[0] = i=1;
}*/

void mul(int a[], int b[], int c[])
{
	int i, j, t;
	
	for (i=1; i<=a[0]; i++)
	{
		for (t=0, j=1; j <= b[0] || t; j++, t/=10)
			c[i+j-1] = ( t += c[i+j-1] + a[i] * b[j] ) % 10;
		if ( i+j-2 > c[0] ) c[0] = i+j-2;
	}
}

void add(int to[], int a[], int b[])
{
	int i, t=0;
	
	for (i=1; i<=a[0] || i<=b[0] || t; i++, t/=10)
		to[ i ] = ( t += (a[i]+b[i]) ) % 10;
	to[ 0 ] = i-1;
}

void div(int a[], int b)
{
	int i, t=0;
	
	for (i=a[0]; i>0; i--, t %= b)
		a[i] = ( t = t*10 + a[i] ) / b;
	for (; a[0] > 1 && !a[a[0]]; a[0]--);
}

void sub(int a[], int b[])
{
	int i, t=0;
	
	for (i=1; i<=a[0]; i++)
		a[i] += ( t = ( a[i]-=(b[i]+t) ) < 0 ) * 10;
		
	for (; a[0] > 1 && ! a[ a[0] ]; a[0]--);
}

int cmp(int a[], int b[])
{
	if ( a[0]-b[0] ) return a[0]-b[0];

	for (int i=a[0]; i>=1; i--)
		if ( a[i]-b[i] ) return a[i]-b[i];
	return 0;	// egalitate
}

void genn(int v[], int c)
{
//	memset(v, 0, sizeof(v)); ???
	int i;
	for (v[0]=c, i=1; i<=c; i++) v[i] = 9;
}

void slowpow(int to[2*maxd], int a[2*maxd], int pw)
{
	int i, aux2[2*maxd];
	
	for (i=1; i<=pw; i++)
	{
		memset(aux2, 0, sizeof(aux2));
		mul(to, a, aux2);
		memcpy(to, aux2, sizeof(aux2));
	}
}

void solve()
{
	int _1[2*maxd];
	int pw, st[2*maxd], dr[2*maxd], mid[2*maxd], i, j, k, max, min, auxp[2*maxd], rez;

	memset(_1, 0, sizeof(_1));
	_1[0] = _1[1] = 1;
	
	for (pw=100; pw>=1; pw--)
	{
		// generez capetele intervalului de cautare
		memset(st, 0, sizeof(st));
		memset(dr, 0, sizeof(dr));
		max = p[0] / pw + ( p[0] % pw != 0 );
		min = max > 2 ? max-2 : 1;
		
		st[ st[0]=min ] = 1;
		genn(dr, max);
		
		// cautarea
		while ( cmp(st, dr) <= 0 )
		{
			// mid = (st+dr)/2;
			memset(mid, 0, sizeof(mid));
			add(mid, st, dr);
			div(mid,  2);
			
			// ridic la putere
			memset(auxp, 0, sizeof(auxp));
			auxp[0] = auxp[1] = 1;
			slowpow(auxp, mid, pw);
			
			rez = cmp(auxp, p);
			
			if ( ! rez )
			{
				// am gasit rezultat
				goto found_result;
			}
			
			if ( rez < 0 )	// rezultatul trebuie sa creasca
			{
				memcpy(st, mid, sizeof(mid));
				add(st, st, _1);
			}
			if ( rez > 0 )
			{
				memcpy(dr, mid, sizeof(mid));
				sub(dr, _1);
			}
		}
	}
	
	memcpy(a, p, sizeof(p));
	b = 1;
	
	return;
	
	found_result :
	
	memcpy(a, mid, sizeof(mid));
	b = pw;
}

void writef()
{
	freopen(_fout, "w", stdout);
	int i;
	
	for (i=a[0]; i>=1; i--) printf("%d", a[i]);
	printf("\n%d\n", b);
}

int main()
{
	readf();
	solve();
	writef();
	
	return 0;
}