problemy z algorytmami SPOJ

0

Witam,postanowiłem porozwiązywać pare zadań ze stronki SPOJ, niektóre już udało mi się rozwiązać ale niektóre są banalnie proste,ale doprowadzają mnie do szału!! Oto niektore z nich:

https://pl.spoj.pl/problems/T_POTEGA/
https://pl.spoj.pl/problems/PP0501A/
https://pl.spoj.pl/problems/PP0504B/
https://pl.spoj.pl/problems/FCTRL3/

Oto poszczególne kody:

Kod do zadania z silnią:

#include <stdio.h>
#include <stdlib.h>


int silnia (int n) 
{
if (n<0)
return 0;
if (n==0 || n==1)
return 1;
return silnia(n-1)*n;
}





int main(void)
{ 
  
	int razy;
	int i;
	int temp;
	long *liczby;
	long *silnie;

	
  
  scanf("%d",&razy);
  
	
  liczby=(long*)malloc(razy*sizeof(long));
  silnie=(long*)malloc(razy*sizeof(long));
	
	for (i=0;i<razy;++i)
		{ 
		 scanf("%ld",&liczby[i]);
		}



	for (i=0;i<razy;++i)
		{
      silnie[i]=silnia(liczby[i]);

	
   
   }



	for (i=0;i<razy;++i)
		printf("%ld %ld\n", silnie[i]/10,(silnie[i]%10)  );


	
	return 0;
}
	

Kod do zadania z potęgowaniem:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

long long pot(long long a,long long b)
{    
     long long wynik=1;
     long long i;
     for (i=0;i<b;++i)
         wynik*=a;
         
     return wynik;
}


int main(void)
{	
	/*clock_t poczatek=clock();
	clock_t koniec;*/
	int razy;
	int i;
	long long  (*liczby)[3];
	


	scanf("%d",&razy);

	liczby=( long long(*)[3] ) malloc(razy*3*sizeof(long long));
	

	for (i=0;i<razy;++i)
		scanf("%lld %lld %lld",&liczby[i][0],&liczby[i][1],&liczby[i][2]);

	for( i=0;i<razy;++i)
		printf("%d\n", ( (pot(liczby[i][0],liczby[i][1]) % liczby[i][2])) );



	

	/*koniec=clock();
	printf("Czas programu: %.3f",((float)(koniec-poczatek)/CLOCKS_PER_SEC ) );*/
	
	getchar();
	getchar();
	return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>


int main(void)
{	
	 clock_t poczatek=clock();
	 clock_t koniec;
	 int razy;
	 int i;
	 int j;
	 int (*liczby)[2];
	 int * NWD;


	scanf("%d",&razy);
	
	liczby=( int(*)[2] ) malloc(razy*2*sizeof(int));			
	NWD=(int*)malloc(razy*sizeof(int) );
	
	
	
	for (i=0;i<razy;++i)
		scanf("%d %d",&liczby[i][0],&liczby[i][1]);							/*Wczytywanie liczb*/	
	



	for (i=0;i<razy;++i)
	{
		int max=liczby[i][0]<liczby[i][1] ? liczby[i][0] : liczby[i][1];		/*Obliczanie NWD */
	
	for (j=1;j<=max;++j)
		if ( liczby[i][0]%j==0 && liczby[i][1]%j==0) NWD[i]=j;
	}




	for (i=0;i<razy;++i)
		printf("%d\n",NWD[i]);

	koniec=clock();
	printf("Czas programu: %.3f",((float)(koniec-poczatek)/CLOCKS_PER_SEC ) );
	
	getchar();
	getchar();
	return 0;
}


Kod programu ze string_merge:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* string_merge(char *, char *);

int main(void)
{
	int razy;
	int i;
	char temp[20];
	char temp2[20];
	char ** tab;
	
		
	scanf("%d",&razy);

	tab=(char**) malloc(razy*sizeof(char*));


	for (i=0;i<razy;++i)
		{	
			
			scanf("%s %s",temp,temp2);
			tab[i]=string_merge(temp,temp2);
			
		}

	for (i=0;i<razy;++i)
		{
			printf("%s\n",tab[i]);
			free(tab[i]);
		}


	
	getchar();
	getchar();
	return 0;
}
	





char* string_merge(char *tab1, char *tab2)
{
	int dlugosc1=strlen(tab1);
	int dlugosc2=strlen(tab2);
	int max=  dlugosc1<=dlugosc2 ? dlugosc1:dlugosc2;
	char*wskaznik;
	int i;
	int j=0;

	wskaznik=(char*) malloc( (2*max*sizeof(char)) +1 );

	for (i=0;i<max;++i)
		{	
			 wskaznik[j]=tab1[i];
			 wskaznik[j+1]=tab2[i];
			 ++++j;
	}

	wskaznik[j]='\0';

	return wskaznik;
}




Problemy przy zadaniach:

  1. Przy silni wyskakuje komunikat że program wykonuje się zbyt długo,ma na to 1s.
  2. Przy potegowaniu nie starcza miejsca dla tak ogromnej liczby jakas jest 81 do 9345 potegi,nie wiem jakiego typu uzyc by nie stracic dokladnosci liczby.
  3. Przy NWD program wykonuje się zbyt długo.
    4.To zadanie mnie najbardziej denerwuje,bo na kazdym moim kompilatorze kompilacja przebiega bez problemu,na ideone.com także wszystkie programy powyższe wykonują się bez problemu,a przy 4 zadaniu na tej stronie mam błąd kompilacji.

Mam nadzieje że mi pomożecie,bo ja już nie mam pomysłów:P

Kod do zadania z NWD:
</code>

0

Chłopie! Ale te zadania właśnie na tym polegają że trzeba tam myśleć a nie klepać kod bez sensu...

  1. Silnia:
    masz podawać tylko DWIE OSTATNIE CYFRY tej silni, nie musisz liczyć całej. Zresztą nie wiem czy wiesz ale silnia to bardzo mocno rosnąca funkcja. Zwykłe typy liczbowe (max 64 bitowe) przechowają ci maksymalnie do 21!...
    Jak poradzić sobie z tym zadaniem?
    Powyżej 4! ostatnia cyfra zawsze będzie 0
    Powyżej 9! ostatnie dwie cyfry zawsze będą 0
    Poza tym tablicowanie tych wyników i wypisanie ich na końcu to idiotyzm. Wypisuj od razu. Nie ma problemu że ci się "wejście pomiesza z wyjściem". Na konsoli tego nie odróżniasz, ale zapewniam cię że komputer sobie z tym radzi...

  2. Z potęgami jest podobnie jak z tą silnią, interesuje cię potęga MODULO pewna liczba. Liczenie całej potęgi jest bez sensu. Weź do ręki kartkę i sprawdź np. co się dzieje kiedy wykonujesz modulo przed kolejnym mnożeniem, a co się dzieje kiedy wykonasz je dopiero po tym mnożeniu. Są różnice?

Do następnych aż szkoda słów. Odstaw komputer i kompilator. Włącz myślenie. Weź do ręki kartkę papieru i ołówek i rozwiązuj problemy! Nie próbuj pisać nawet jednej linijki kodu zanim nie rozwiążesz danego zadania na kartce...

0

Tytuł zadania z silnią:
496. Dwie cyfry silnii

Radzę się skupić na zaznaczonym fragmencie, bo dla najtrudniejszego przypadku, czyli 1 000 000 000!, otrzymasz liczbę z prawie 250 milionami zer, która średnio się mieści z typie long :)
http://www.wolframalpha.com/input/?i=1000000000!

Innych programów nie chce mi się teraz sprawdzać, ale pamiętaj, że jeśli zadanie na SPOJu przekracza ci limit czasu, to na 99,999% powinieneś pomyśleć nad algorytmem (nawet nie myśl o optymalizacjach typu zamiana pętli for na while :) )

0

Człowieku nawet ci się do wiki nie chciało zajrzeć! Liczenie NWD w ten sposób to po prostu jakaś porażka. Na wiki masz link do szybkiego rozwiązania, zaproponowanego ponad 2500 lat temu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1