Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
Algoritmi - Qualifiche Facebook Hacker Cup - Find The Min
Forum - Algoritmi - Qualifiche Facebook Hacker Cup - Find The Min

Pagine: [ 1 2 3 4 5 ] Precedente | Prossimo
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 20:05
Sabato, 26/01/2013
Facebook Hacker Cup: https://www.facebook.com/hackercup?fref=ts

Qualcuno e' riuscito a risolverlo con un algoritmo veloce? (Deve terminare entro 5 minuti).

Problema:

Testo quotato


After sending smileys, John decided to play with arrays. Did you know that hackers enjoy playing with arrays? John has a zero-based index array, m, which contains n non-negative integers. However, only the first k values of the array are known to him, and he wants to figure out the rest.

John knows the following: for each index i, where k <= i < n, m[ i] is the minimum non-negative integer which is *not* contained in the previous *k* values of m.

For example, if k = 3, n = 4 and the known values of m are [2, 3, 0], he can figure out that m[3] = 1.

John is very busy making the world more open and connected, as such, he doesn't have time to figure out the rest of the array. It is your task to help him.

Given the first k values of m, calculate the nth value of this array. (i.e. m[n - 1]).

Because the values of n and k can be very large, we use a pseudo-random number generator to calculate the first k values of m. Given positive integers a, b, c and r, the known values of m can be calculated as follows:

m[0] = a
m[i ] = (b * m[i - 1] + c) % r, 0 < i < k
Input
The first line contains an integer T (T <= 20), the number of test cases.
This is followed by T test cases, consisting of 2 lines each.
The first line of each test case contains 2 space separated integers, n, k (1 <= k <= 105, k < n <= 109).
The second line of each test case contains 4 space separated integers a, b, c, r (0 <= a, b, c <= 109, 1 <= r <= 109).
Output
For each test case, output a single line containing the case number and the nth element of m.



Input di esempio:
Testo quotato


5
97 39
34 37 656 97
186 75
68 16 539 186
137 49
48 17 461 137
98 59
6 30 524 98
46 18
7 11 9 46



Output:
Testo quotato


Case #1: 8
Case #2: 38
Case #3: 41
Case #4: 40
Case #5: 12



Input usato per la valutazione (questo dev'essere eseguito in meno di 5 minuti):
Testo quotato


20
131 74
1 9 10 78736
177 73
7 7 5 56401
164 96
76 2 193 164
137 49
48 17 461 137
1000000000 100000
999999999 1 999999999 1000000000
249718282 93729
1 5 6 999917908
640834505 28785
3 9 1 999946125
1000000000 1
12 7 74 12
28 21
6 5 1 85919
59 26
14 19 681 59
186 75
68 16 539 186
232959116 56689
4 9 1 999903057
110 53
7 7 1 64417
97 39
34 37 656 97
714311129 39521
9 5 9 999998192
220 88
1 8 3 58265
78 51
3 5 5 51230
1000000000 100000
99999 1 99999 100000
977365070 59489
8 5 9 999966210
46 18
7 11 9 46



Questa e' la mia soluzione (troppo lenta):

Codice sorgente - presumibilmente Delphi

  1. #!/usr/bin/ruby
  2.  
  3. counter = 0
  4. numElements = 0
  5. file = File.new("find_the_mintxt.txt", "r")
  6. while (line = file.gets)
  7.     counter = counter + 1
  8.         if counter == 1
  9.                 numElements = line.to_i
  10.         else
  11.                 nkline = line.chomp
  12.                 abcrline = file.gets.chomp
  13.                 m = []
  14.                 n,k = nkline.split(' ')[0].to_i, nkline.split(' ')[1].to_i
  15.                 a,b,c,r = abcrline.split(' ')[0].to_i, abcrline.split(' ')[1].to_i,  abcrline.split(' ')[2].to_i,  abcrline.split(' ')[3].to_i
  16.  
  17.                 dic = {}
  18.                 dic[a] = 1
  19.  
  20.                 m[0] = a
  21.                 for i in 1..(k - 1)
  22.                         m[i] = (b * m[i - 1] + c) % r
  23.                         if dic[m[i]]
  24.                                 dic[m[i]] += 1
  25.                         else
  26.                                 dic[m[i]] = 1
  27.                         end
  28.                 end
  29.  
  30.                 for i in k..(n - 1)
  31.                         c = 0
  32.                         c += 1 while not dic[c].nil? #<---- LENTO, come si fa ad accelerare?
  33.                         m[i] = c
  34.  
  35.                         if dic[m[i]]
  36.                                 dic[m[i]] += 1
  37.                         else
  38.                                 dic[m[i]] = 1
  39.                         end
  40.                        
  41.                         dic[m[i - k]] -= 1
  42.                         dic.delete(m[i - k]) if dic[m[i - k]] == 0
  43.                 end
  44.  
  45.         puts "Case ##{counter - 1}: #{m[n-1]}"
  46.         end
  47. end
  48. file.close



Che ne pensate?

Ultima modifica effettuata da pierotofy il 26/01/2013 alle 20:06


Il mio blog: https://piero.dev
PM Quote
Avatar
tasx (Dev Team)
Expert


Messaggi: 439
Iscritto: 15/12/2008

Segnala al moderatore
Postato alle 21:05
Sabato, 26/01/2013
Urca tra poco ci arrivo... sbrigo il secondo e arrivo ;)

PM Quote
Avatar
Maury91 (Member)
Expert


Messaggi: 531
Iscritto: 18/09/2006

Segnala al moderatore
Postato alle 3:09
Domenica, 27/01/2013
Testo quotato

Postato originariamente da pierotofy:


Problema:

Testo quotato


After sending smileys, John decided to play with arrays. Did you know that hackers enjoy playing with arrays? John has a zero-based index array, m, which contains n non-negative integers. However, only the first k values of the array are known to him, and he wants to figure out the rest.

John knows the following: for each index i, where k <= i < n, m[ i] is the minimum non-negative integer which is *not* contained in the previous *k* values of m.

For example, if k = 3, n = 4 and the known values of m are [2, 3, 0], he can figure out that m[3] = 1.

John is very busy making the world more open and connected, as such, he doesn't have time to figure out the rest of the array. It is your task to help him.

Given the first k values of m, calculate the nth value of this array. (i.e. m[n - 1]).

Because the values of n and k can be very large, we use a pseudo-random number generator to calculate the first k values of m. Given positive integers a, b, c and r, the known values of m can be calculated as follows:

m[0] = a
m[i ] = (b * m[i - 1] + c) % r, 0 < i < k
Input
The first line contains an integer T (T <= 20), the number of test cases.
This is followed by T test cases, consisting of 2 lines each.
The first line of each test case contains 2 space separated integers, n, k (1 <= k <= 105, k < n <= 109).
The second line of each test case contains 4 space separated integers a, b, c, r (0 <= a, b, c <= 109, 1 <= r <= 109).
Output
For each test case, output a single line containing the case number and the nth element of m.



Input di esempio:
Testo quotato


5
97 39
34 37 656 97
186 75
68 16 539 186
137 49
48 17 461 137
98 59
6 30 524 98
46 18
7 11 9 46



Output:
Testo quotato


Case #1: 8
Case #2: 38
Case #3: 41
Case #4: 40
Case #5: 12





Ho creato i primi k valori di m con la formula
m[0]=a;
m=(b*m[i-1]+c)%r;

e mi torna che m contiene :
34 71 82 4 28 43 16 84 78 50 81 64 17 24 89 69 8 79 87 92 83 41 39 62 40 2 51 21 75 36 48 7 42 76 73 59 26 66 91

come può il risultato (ovvero l'n-esimo valore di m) essere 8 se 8 è contenuto in già nei primi k elementi?

Magari ho capito male il testo...
quello che ho capito è questo :

i primi k valori della matrice son calcolati secondo la formula che danno loro e con le loro variabili...

i valori da k a n li dobbiamo calcolare noi.. e sappiamo che ogni valore che calcoliamo è il valore minimo che non è contenuto nella parte antecedente della matrice..

se è come ho capito questo è il codice che ho pensato :
Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int comp(const int * a,const int * b)
  5. {
  6.   if (*a==*b)
  7.     return 0;
  8.   else
  9.     if (*a < *b)
  10.         return -1;
  11.      else
  12.       return 1;
  13. }
  14.  
  15. long int testcase(long int a,long int b, long int c, long int r, long int n, long int k) {
  16.     long int s[k],i,p,now;
  17.     s[0]=a;
  18.     for (i=1;i<k;i++)
  19.         s[i]=(b*s[i-1]+c)%r;
  20.     //Ordino l'array
  21.     qsort(s,k,sizeof(long int),comp);
  22.     //Setto che il numero a cui sono ora è 0 e l'elemento di s che controllo è 0
  23.     now=p=0;
  24.     for (i=k;i<n;i++) {
  25.         while(now>=s[p]) {
  26.             if (now==s[p])
  27.                 now++;
  28.             else
  29.                 p++;
  30.         }
  31.         now++;
  32.     }
  33.     return now-1;
  34.     /*for (i=0;i<n;i++)
  35.         printf("%d ",m[i]);*/
  36. }
  37.  
  38. int main() {
  39.     FILE *f,*f2;
  40.     int cont,i;
  41.     long int n,k,a,b,c,r;
  42.     f = fopen("input.txt","r");
  43.     f2 = fopen("output.txt","w");
  44.     fscanf(f,"%d",&cont);
  45.     for (i=0;i<cont;i++) {
  46.         fscanf(f,"%d %d",&n,&k);
  47.         fscanf(f,"%d %d %d %d",&a,&b,&c,&r);
  48.         fprintf(f2,"Case #%d : %d\n",i+1,testcase(a,b,c,r,n,k));
  49.     }
  50.     fclose(f);
  51.     fclose(f2);
  52.     return 0;
  53. }



L'ho provato sui dati di piero... ci mette circa 30 secondi

Ultima modifica effettuata da Maury91 il 27/01/2013 alle 3:28
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 4:22
Domenica, 27/01/2013
I primi *k* elementi, nel senso che ad ogni indice i devi considerare i k elementi precedenti.

Ad esempio, se k = 5 e n = 10, per i = 8 devi considerare gli elementi 3,4,5,6,7 (5 elementi precedenti, omettendo 0,1,2).


Il mio blog: https://piero.dev
PM Quote
Avatar
Maury91 (Member)
Expert


Messaggi: 531
Iscritto: 18/09/2006

Segnala al moderatore
Postato alle 5:52
Domenica, 27/01/2013
ok capito..
ho tentato questa soluzione ma si impalla... ma credo il ragionamento sia corretto :
Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. typedef struct findmin_t {
  5.     int num;
  6.     struct findmin_t* prev;
  7.     struct findmin_t* next;
  8.     struct findmin_t* next_del;
  9. } findmin;
  10.  
  11. findmin *min,*f_del;
  12.  
  13. void insert_order(findmin *ins) {
  14.     findmin *s;
  15.     s=min;
  16.     if (ins->num<s->num) {
  17.         s->prev=ins;
  18.         ins->next=s;
  19.         min=ins;
  20.     } else {
  21.         while((s->num<ins->num)&&(s->next!=NULL)) {
  22.             s=s->next;
  23.         }
  24.         if (s->num<ins->num) {
  25.             s->next=ins;
  26.             ins->prev=s;
  27.             ins->next=NULL;
  28.         } else {
  29.             ins->prev=s->prev;
  30.             s->prev->next=ins;
  31.             ins->next=s;
  32.             s->prev=ins;
  33.         }
  34.     }
  35. }
  36.  
  37. long int testcase(long int a,long int b, long int c, long int r, long int n, long int k) {
  38.     long int s[k],ii,i,p,now,to_del;
  39.     findmin *max,*l_del,*l_min=NULL,*sup,*l_ins;
  40.     int stalled=0;
  41.     int l;
  42.     s[0]=a;
  43.     min = (findmin*)malloc(sizeof(findmin));
  44.     min->num=a;
  45.     min->prev=NULL;
  46.     min->next=NULL;
  47.     min->next_del=NULL;
  48.     f_del=l_ins=min;
  49.     for (i=1;i<k;i++) {
  50.         s[i]=(b*s[i-1]+c)%r;
  51.         sup=(findmin*)malloc(sizeof(findmin));
  52.         sup->num=s[i];
  53.         l_ins->next_del=sup;
  54.         insert_order(sup);
  55.         l_ins=sup;
  56.     }
  57.     for (i=k;i<n;i++) {
  58.         now=0;
  59.         if (min->num==0) {
  60.             //if (l_min==NULL)
  61.                 sup=min;
  62.             /*else {
  63.                 sup=l_min;
  64.             }*/
  65.             while((sup->next!=NULL)&&(now>=sup->num)) {
  66.                 if (now==sup->num)
  67.                     now++;
  68.                 else {
  69.                     sup=sup->next;
  70.                 }
  71.             }
  72.             if (sup->next==NULL)
  73.                 now=sup->num+1;
  74.             l_min=sup;
  75.         }
  76.  
  77.         //Eliminazione
  78.         if (f_del->prev!=NULL)
  79.             f_del->prev->next = f_del->next;
  80.         else
  81.             min=f_del->next;
  82.         if (f_del->next!=NULL)
  83.             f_del->next->prev = f_del->prev;
  84.         sup=f_del;
  85.         f_del=f_del->next_del;
  86.         free(sup);
  87.         sup=(findmin*)malloc(sizeof(findmin));
  88.         sup->num=now;
  89.         l_ins->next_del=sup;
  90.         insert_order(sup);
  91.         l_ins=sup;
  92.     }
  93.     return now;
  94. }
  95.  
  96. int main() {
  97.     FILE *f,*f2;
  98.     int cont,i;
  99.     long int n,k,a,b,c,r;
  100.     f = fopen("input.txt","r");
  101.     f2 = fopen("output.txt","w");
  102.     fscanf(f,"%d",&cont);
  103.     for (i=0;i<cont;i++) {
  104.         fscanf(f,"%d %d",&n,&k);
  105.         fscanf(f,"%d %d %d %d",&a,&b,&c,&r);
  106.         printf("Case #%d : %d\n",i+1,testcase(a,b,c,r,n,k));
  107.     }
  108.     fclose(f);
  109.     fclose(f2);
  110.     return 0;
  111. }


Ultima modifica effettuata da Maury91 il 27/01/2013 alle 7:00
PM Quote
Avatar
Il Totem (Admin)
Guru^2


Messaggi: 3635
Iscritto: 24/01/2006

Segnala al moderatore
Postato alle 13:37
Domenica, 27/01/2013
Secondo me c'è qualche trucco per dedurre il nuovo elemento. Qualsiasi algoritmo con complessità lineare non può andar bene (e non c'è modo di scendere al di sotto di O(n) con questo approccio).

PM Quote
Avatar
Maury91 (Member)
Expert


Messaggi: 531
Iscritto: 18/09/2006

Segnala al moderatore
Postato alle 14:24
Domenica, 27/01/2013
Testo quotato

Postato originariamente da Il Totem:

Secondo me c'è qualche trucco per dedurre il nuovo elemento. Qualsiasi algoritmo con complessità lineare non può andar bene (e non c'è modo di scendere al di sotto di O(n) con questo approccio).



allora ho scoperto le seguenti cose :
esiste una serie di k+1 elementi che si ripete sempre, quindi basta calcolare questi...

ho trovato un modo per "dedurre il nuovo elemento" ma sto avendo alcuni problemi a ottimizzare il codice

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. typedef struct findmin_t {
  5.     int num;
  6.     struct findmin_t* prev;
  7.     struct findmin_t* next;
  8.     struct findmin_t* next_del;
  9. } findmin;
  10.  
  11. findmin *min,*f_del;
  12.  
  13. void insert_order(findmin *ins) {
  14.     findmin *s;
  15.     s=min;
  16.     if (ins->num<=s->num) {
  17.         s->prev=ins;
  18.         ins->next=s;
  19.         min=ins;
  20.     } else {
  21.         while((s->num<ins->num)&&(s->next!=NULL)) {
  22.             s=s->next;
  23.         }
  24.         if (s->num<ins->num) {
  25.             s->next=ins;
  26.             ins->prev=s;
  27.             ins->next=NULL;
  28.         } else {
  29.             ins->prev=s->prev;
  30.             s->prev->next=ins;
  31.             ins->next=s;
  32.             s->prev=ins;
  33.         }
  34.     }
  35. }
  36.  
  37. long int testcase(long int a,long int b, long int c, long int r, long int n, long int k) {
  38.     long int s[k+1],i,now;
  39.     findmin *exit=NULL,*l_del,*l_min=NULL,*sup,*l_ins,*found,*ff;
  40.     int stalled=0;
  41.     int l;
  42.     s[0]=a;
  43.     min = (findmin*)malloc(sizeof(findmin));
  44.     min->num=a;
  45.     min->prev=NULL;
  46.     min->next=NULL;
  47.     min->next_del=NULL;
  48.     f_del=l_ins=min;
  49.     for (i=1;i<k;i++) {
  50.         s[i]=(b*s[i-1]+c)%r;
  51.         sup=(findmin*)malloc(sizeof(findmin));
  52.         sup->num=s[i];
  53.         l_ins->next_del=sup;
  54.         insert_order(sup);
  55.         l_ins=sup;
  56.     }
  57.     l=k;
  58.     for (i=k;i<n;i++) {
  59.         if (stalled) {
  60.             now=s[i%(k+1)];
  61.         } else {
  62.             now=0;
  63.             if (min->num==0) {
  64.                 if (l_min==NULL)
  65.                     sup=min;
  66.                 else {
  67.                     //Ultimo numero piccolo inserito
  68.                     //Se il numero uscente
  69.                     if (exit->num<l_min->num) {
  70.                         if (l_ins->num<exit->num) {
  71.                             now = l_ins->num;
  72.                             sup = l_ins;
  73.                         }
  74.                         else {
  75.                             now = exit->num;
  76.                             sup = exit;
  77.                         }
  78.                     }
  79.                     else{
  80.                         if (l_ins->num<l_min->num) {
  81.                             now = l_ins->num;
  82.                             sup = l_ins;
  83.                         }else {
  84.                             now = l_min->num;
  85.                             sup = l_min;
  86.                         }
  87.                     }
  88.                     //printf("^%d^",now);
  89.                     if (sup->prev!=NULL)
  90.                         sup = sup->prev;
  91.                     //sup=min;
  92.                     //printf("-%d,%d,%d-",exit->num,l_min->num,l_ins->num);
  93.                 }
  94.                 while((sup->next!=NULL)&&(now>=sup->num)) {
  95.                     if (now==sup->num)
  96.                         now++;
  97.                     else {
  98.                         sup=sup->next;
  99.                     }
  100.                 }
  101.                 //printf(" >%d<",sup->num);
  102.                 if (sup->num==now)
  103.                     now++;
  104.                 l_min=sup;
  105.             }
  106.             //Eliminazione
  107.             if (f_del->prev!=NULL)
  108.                 f_del->prev->next = f_del->next;
  109.             else
  110.                 min=f_del->next;
  111.             if (f_del->next!=NULL)
  112.                 f_del->next->prev = f_del->prev;
  113.             if (exit!=NULL)
  114.                 free(exit);
  115.             exit=f_del;
  116.             f_del=f_del->next_del;
  117.             sup=(findmin*)malloc(sizeof(findmin));
  118.             sup->num=now;
  119.             l_ins->next_del=sup;
  120.            
  121.             //Qua sta il problema non riesco a fare l'inserimento ordinato con questo codice... si crea uno scompenso e il risultato risulta diverso...
  122.  
  123.             /*if (l_min->prev != NULL)
  124.                 printf("\n>>%d %d %d - %d<<\n",l_min->prev->num,sup->num,l_min->num,min->num);
  125.             else
  126.                 printf("\n>>%d %d<<\n",sup->num,l_min->num);*/
  127.             /*if (sup->num<min->num){
  128.                 min->prev=sup;
  129.                 sup->next=min;
  130.                 min=sup;
  131.             } else {
  132.                 //Se è la fine
  133.                 if (sup->num>=l_min->num){
  134.                     l_min->next=sup;
  135.                     sup->prev=l_min;
  136.                     sup->next=NULL;
  137.                 } else {
  138.                     sup->prev=l_min->prev;
  139.                     l_min->prev->next=sup;
  140.                     sup->next=l_min;
  141.                     l_min->prev=sup;
  142.                 }
  143.             }*/
  144.  
  145.             insert_order(sup);
  146.  
  147.             l_ins=sup;
  148.             s[i%(k+1)]=now;
  149.             //printf("\n%d ",now);
  150.             if ((now==k)&&(i%k==0)) stalled=1;
  151.         }
  152.     }
  153.     return now;
  154. }
  155.  
  156. int main() {
  157.     FILE *f,*f2;
  158.     int cont,i;
  159.     long int n,k,a,b,c,r;
  160.     f = fopen("input.txt","r");
  161.     f2 = fopen("output.txt","w");
  162.     fscanf(f,"%d",&cont);
  163.     for (i=0;i<cont;i++) {
  164.         fscanf(f,"%d %d",&n,&k);
  165.         fscanf(f,"%d %d %d %d",&a,&b,&c,&r);
  166.         printf("Case #%d : %d\n",i+1,testcase(a,b,c,r,n,k));
  167.     }
  168.     fclose(f);
  169.     fclose(f2);
  170.     return 0;
  171. }



il mio scopo è aumentare l'efficienza dell'algoritmo non usando insert_order quando inserisco i nuovi visto che per rilevare quale numero mettere ho già gli elementi tra i quali inserirlo... non riesco a capire cosa c'è di sbagliato nella parte commentata visto che impazzisce...

Ultima modifica effettuata da Maury91 il 27/01/2013 alle 14:32
PM Quote
Avatar
Il Totem (Admin)
Guru^2


Messaggi: 3635
Iscritto: 24/01/2006

Segnala al moderatore
Postato alle 14:37
Domenica, 27/01/2013
Probabilmente quella serie è dovuta all'algoritmo che genera i numeri pseudocasuali. Comunque una lista non è la struttura dati migliore. E poi se mischi il codice che gestisce la lista con quello che risolve il problema non si capisce molto: sono su due livelli di astrazione diversi.

PM Quote
Avatar
Maury91 (Member)
Expert


Messaggi: 531
Iscritto: 18/09/2006

Segnala al moderatore
Postato alle 14:39
Domenica, 27/01/2013
si ma se uso l'insert_order quando ho già qual'è il nodo in cui inserire perdo di efficienza...

a me la lista sembra la struttura migliore per gestire il problema... tra tutti gli algoritmi che ho provato... questo senza nemmeno essere ottimizzato risulta il più veloce...

http://www.facebook.com/photo.php?fbid=4859555939057&set=a ...

http://www.facebook.com/photo.php?fbid=4859688902381&set=a ...

Ultima modifica effettuata da Maury91 il 27/01/2013 alle 15:00
PM Quote
Pagine: [ 1 2 3 4 5 ] Precedente | Prossimo