A pacata cidade de South Park nada de pacata tem. Butters, digo, Professor Chaos está aterrorizando mais uma vez! Ele busca o que ninguém jamais procurou, as ocorrências de alguns números pseudo-aleatórios modulares!
O desejo de professor Chaos é muito simples. Ele possui duas sementes para geração de números pseudo-aleatórios e precisa saber quantas ocorrências de alguns números ocorrem a cada (isso mesmo cem mil) gerações de números pseudo-aleatórios para as duas sementes que ele possui.
A entrada possui um único caso de teste contendo um número indeterminado de linhas.
A primeira possui dois números inteiros sem sinal, e , representanto, respectivamente, a primeira semente e a segunda semente.
rand_r()
para gerar os números pseudo-aleatóriosDepois da primeira linha existirão diversas linhas contendo dois inteiros e , representando, respectivamente, MÓDULO (em C
representado pelo sinal %
) e o número que seja se procurar.
Para cada linha contendo e você deve responder quantas ocorrências de aconteceram para cada um dos números ( de cada semente) pseudo-aleatórios módulo .
Você já deve ter percebido que esse problema talvez funcione mais rapidamente se for utilizado o conceito de threads e semáforos.
Para simplificar o entendimento, vou explicar nesta seção um exemplo reduzido, que ao invés de gerar valores, geraremos somente .
Caso a entrada fosse:
300 801 (ref:sementes)
8 6
512 100
Na linha (sementes), recebemos duas sementes, e . Gerando números pseudo-aleatórios com essas sementes, teríamos:
1179231837 1613409366 312769636 1637092777 840974024
1471841391 193279630 141119683 166125014 238450767
A primeira linha os números gerados da semente e a segunda dos números de . Nunca modifique esses números, pois eles serão utilizados para toda as outras consultas.
Agora precisaríamos processar as próximas linhas, o primeiro é que busca a quantidade de ocorrências de , calculando o MOD para cada pseudo-aleatório (gerados e armazenaods anteriormente) teríamos:
5 6 4 1 0
7 6 3 6 7
Já que queremos saber a quantidade de ocorrências de , obtemos 3
ocorrências. Portanto, imprime .
Já para a segunda linha com buscando ocorrências de . Teríamos os seguintes números em módulo , calculados dos números pseudo-aleatórios do primeiro passo:
93 86 100 425 200
184 259 385 368 13
Neste caso temos somente uma ocorrência de , portanto imprimiria .
Nosso amigo Chaos possui uma quase implementação, pena que muitos passos estão faltando.
void calcula_perguntas(unsigned int s)
{
int v[MAXRANDOM];
for(int i=0;i<MAXRANDOM;i++)
v[i]=rand_r(&s);
int mi,bi;
while(ESPERA(mi,bi))
{
conta=0;
for(int i=0;i<MAXRANDOM;i++)
if(v[i]%mi==bi)
conta++;
somaglobal+=conta;
CALCULOFEITO
}
}
int main(void)
{
leia(s1,s2);
cria_thread(calcula_perguntas,s1);
cria_thread(calcula_perguntas,s2);
while(leia(mi,bi))
{
LIBERATHREADS;
AGUARDECALCULOTHREADS;
printf("%d\n",somaglobal);
}
}
A abordagem feita por Chaos é muito ingênua e deve demorar bastante em entradas maiores. Uma abordagem parecida com produtor-consumidor é mais adequada, algo como feito no exercício do get_ticket
.
100 200
8 7
256 7
1000000 533
24961
734
0
5270 22136
705 416
604 478
318 316
583 163
344 137
353 129
762 703
550 124
249 49
351 237
293
350
600
319
575
558
254
359
831
563
27809 12061
365 19
975 42
525 154
18 0
384 236
291 27
950 785
290 141
183 20
904 268
544
190
399
11109
525
657
202
698
1061
252
3732 28201
15 4
334 311
715 341
147 43
403 66
307 186
384 236
309 56
185 145
394 218
13355
613
276
1289
511
644
507
650
1081
504
Author: Bruno Ribas