Cod sursa(job #273076)

Utilizator MarcvsHdrMihai Leonte MarcvsHdr Data 8 martie 2009 02:13:33
Problema GFact Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.59 kb
# include <stdio.h>
# include <math.h>

# define MAXP 5000
# define MAXL 1600
# define BAZA 100000
# define NRCFB 5

typedef struct {long int len;long int nr[MAXL+1];} NUMAR;

long int ciur[MAXP+1],ciurlen,p,q;
long int fact[MAXP+1],factlen,rep[MAXP+1];
NUMAR solp[MAXP+1];

NUMAR sol;

long int min(long int a, long int b) {if (a>b) return b; return a;}
long int max(long int a, long int b) {if (a>b) return a; return b;}
void scrie(NUMAR &a, FILE *g);

/////
// NUMAR HANDLERS
/////

void make_0(NUMAR &a) {a.len=1;a.nr[1]=0;}
void make_1(NUMAR &a) {a.len=1;a.nr[1]=1;}

void normalizeaza(NUMAR &a)
{
     a.nr[a.len+1]=0;
     long int i;
     for (i=1;i<=a.len;i++)
     if (a.nr[i]>=BAZA)
            {
            a.nr[i+1]+=a.nr[i]/BAZA;
            a.nr[i]%=BAZA;
            }
     while (a.nr[a.len+1])
           {
           a.len++;
           a.nr[a.len+1]=a.nr[a.len]/BAZA;
           a.nr[a.len]%=BAZA;
           }
}

void inmulteste_scalar(NUMAR &a, long int p)
{
     long int i;
     for (i=1;i<=a.len;i++) a.nr[i]*=p;
     normalizeaza(a);
}

void aduna_scalar(NUMAR &a, long int p)
{
     a.nr[1]+=p;
     normalizeaza(a);
}

void aduna(NUMAR &a, NUMAR &b)
{
     long int i,l=min(a.len,b.len);
     for (i=1;i<=l;i++) a.nr[i]+=b.nr[i];
     for (i=l+1;i<=b.len;i++) a.nr[i]=b.nr[i];
     a.len=max(a.len,b.len);
     normalizeaza(a);
}

long int mai_mare(NUMAR &a, NUMAR &b)
{
     //scrie(a,stdout);
     //scrie(b,stdout);
     if (a.len>b.len) return 1;
     if (a.len<b.len) return 0;
     long int i=a.len;
     while (i)
           {
           if (a.nr[i]>b.nr[i]) return 1;
           if (a.nr[i]<b.nr[i]) return 0;
           i--;
           }
     return 0;
}

void putere(NUMAR &a, long int baza, long int p)
{
     long int i;
     for (i=1;i<=p;i++)
         {
         inmulteste_scalar(a,baza);
         normalizeaza(a);
         }
}        

//////
// INPUT & OUTPUT
//////

void citire()
{
     FILE *f=fopen("gfact.in","r");
     fscanf(f,"%ld%ld",&p,&q);
     fclose(f);
}

long int prim(long int a)
{
     long int i;
     for (i=1;i<=ciurlen&&ciur[i]*ciur[i]<=a;i++)
         if (a%ciur[i]==0) return 0;
     return 1;
}

void make_ciur()
{
     long int i,upper_bound=(long int)sqrt(p)+1;
     ciur[1]=2;
     ciurlen=1;
     for (i=3;i<=upper_bound;i++)
         if (prim(i)) ciur[++ciurlen]=i;
}

void factorizeaza_p()
{
     long int i;
     for (i=1;p!=1;i++)
         {
         if (p%ciur[i]==0)
            {
            fact[++factlen]=ciur[i];
            rep[factlen]=0;
            while (p%ciur[i]==0) 
                  {
                  p/=ciur[i];
                  rep[factlen]++;
                  }
            }
         if (p!=1&&ciur[i]*ciur[i]>p)
            {
            fact[++factlen]=p;
            rep[factlen]=1;
            break;
            }
         }
}
           
void inmulteste_rep_q()
{
     long int i;
     for (i=1;i<=factlen;i++) rep[i]*=q;
}

long int det_max(long int &rep, long int baza)
{
     long int sol=1,p=1;
     while (p*baza+1<=rep)
           {
           p=p*baza+1;
           sol++;
           }
     rep-=p;
     return sol;
}

void calculeaza()
{
     long int i,max;NUMAR aux;
     for (i=1;i<=factlen;i++) //pt fiecare factor prim
         {
         make_0(solp[i]);
         while (rep[i])
               {
               //determinam puterea maxima a lui p in rep
               max=det_max(rep[i],fact[i]);
               make_1(aux);
               putere(aux,fact[i],max);
               aduna(solp[i],aux);
               }
         }
}

long int ncf(long int a)
{
     if (a==0) return 1;
     long int sol=0;
     while (a) {sol++;a/=10;}
     return sol;
}

void scrie(NUMAR &a, FILE *g)
{
     long int i,nr0;
     fprintf(g,"%ld",a.nr[a.len]);
     i=a.len-1;
     while (i)
           {
           nr0=NRCFB-ncf(a.nr[i]);
           while (nr0--) fprintf(g,"0");
           fprintf(g,"%ld",a.nr[i]);
           }
     fprintf(g,"\n");
}

void scrie_fisier(NUMAR &a)
{
     FILE *g=fopen("gfact.out","w");
     scrie(a,g);
     fclose(g);
}

void get_solution()
{
     sol=solp[1];
     long int i;
     //for (i=1;i<=factlen;i++) scrie(solp[i],stdout);
     for (i=2;i<=factlen;i++)
         if (mai_mare(solp[i],sol)) 
            {
            sol=solp[i];
            }
}

int main()
{
    citire();
    make_ciur();
    factorizeaza_p();
    inmulteste_rep_q();
    calculeaza();
    get_solution();
    scrie_fisier(sol);
    return 0;
}