// reprezentacja liczby (opis wiersza tablicy liczby):
// na pozycji -1 jest liczba zajętych komórek (liczonych od 0)
// na następnych zapisana jest sama liczba, na zasadzie a[0]+10000*a[1]+...
// podczas obliczeń w zerowym wierszu zapisana jest sprawdzana liczba,
// w pierwszym i drugim są liczby określające zakres przeszukiwania,
// pozostałe służą do obliczeń
local liczby[0..16,-1..32];
// wejściowa liczba (jak wyżej, ale jedna więc bez tablicy)
shared liczba[-1..32];
// ilość procesorów do uruchomienia
shared proc_number;
// tablica wyników - interpretacja jak powyżej
shared wyniki[0..63,-1..32];
// tablica pomocnicza
shared zakresy[0..64,-1..32];
local proc;
//----------------------------------
// pomocnicza funkcja służąca do przepisania liczby z jednego wiersza do
// drugiego
function przepisz(a,b)
begin
//----------------------------------
// funkcja tworząca liczbę w postaci tablicowej z liczby podanej jako parametr
function na_tablice(x,c)
local i;
begin
i:=0;
while x>0 do
begin
x:=x/10000;
i:=i+1;
liczby[c,-1]:=i;
//----------------------------------
// funkcja sprawdzająca czy dana liczba (tablica) jest zerem
function zero(a)
begin
else return 0;
//----------------------------------
// funkcja porównująca dwie liczby
// zwraca odpowiednio <0, 0, >0 jeśli a<b, a=b, a>c
function porownaj(a,b)
local i;
begin
if liczby[a,-1]<>liczby[b,-1] then return liczby[a,-1]-liczby[b,-1];
for i:=liczby[a,-1]-1 downto 0 do
if liczby[a,i]<>liczby[b,i] then return liczby[a,i]-liczby[b,i];
return 0;
end;
//----------------------------------
// dodaje dwie liczby do siebie (a+b->c)
function dodaj(a,b,c)
local d;
local i;
local cn;
local p;
begin
else d:=liczby[b,-1];
p:=0;
for i:=0 to d-1 do
begin
liczby[c,i]:=cn%10000;
p:=cn/10000;
if p>0 then begin liczby[c,d]:=p; liczby[c,-1]:=d+1; end;
else liczby[c,-1]:=d;
//----------------------------------
// "udziwnione" dodawanie
function dodaj1(a,b,n,c)
local i;
local cn;
local p;
begin
cn:=liczby[c,n]+b;
liczby[c,n]:=cn%10000;
if cn>10000 then
begin
while p>0 do
begin
liczby[c,i]:=cn%10000;
p:=cn/10000;
i:=i+1;
if i>liczby[c,-1] then liczby[c,-1]:=i;
//----------------------------------
// odejmuje od siebie dwie liczby i zwraca 0 albo, jeśli a<b, zwraca -1
function odejmij(a,b,c)
local i;
local p;
local d;
local cn;
begin
if porownaj(a,b)<0 then return -1;
d:=liczby[a,-1]-1;
p:=0;
for i:=0 to d do
begin
if cn<0 then begin cn:=cn+10000; p:=1; end;
else p:=0;
liczby[c,i]:=cn;
i:=d;
while liczby[c,i]=0 and i>0 do i:=i-1;
if i=0 and liczby[c,0]=0 then liczby[c,-1]:=0;
else liczby[c,-1]:=i+1;
return 0;
//----------------------------------
// mnoży podaną liczbę przez 10 (przesunięcie w lewo o jedną cyfrę)
function razy10(a,c)
local i;
local p;
local cn;
begin
for i:=0 to liczby[a,-1]-1 do
begin
liczby[c,i]:=cn%10000;
p:=cn/10000;
if p>0 then begin liczby[c,i]:=p; liczby[c,-1]:=i+1; end;
else liczby[c,-1]:=i;
//----------------------------------
// analogiczne dzielenie przez 10
function dziel10(a,c)
local i;
local p;
local cn;
local d;
begin
for i:=d-1 downto 0 do
begin
liczby[c,i]:=cn/10;
p:=cn%10;
if liczby[c,d-1]=0 then liczby[c,-1]:=d-1;
else liczby[c,-1]:=d;
//----------------------------------
// dzieli liczbę w postaci tablicowej przez liczbę całkowitą
function podziel1(a,b,c)
local k;
local cn;
local p;
local i;
begin
przepisz(a,k);
for i:=-1 to 32 do liczby[c,i]:=0;
p:=0;
for i:=liczby[a,-1]-1 downto 0 do
begin
liczby[c,i]:=cn;
p:=(10000*p+liczby[k,i])-b*cn;
i:=liczby[a,-1]-1;
while i>=0 and liczby[c,i]=0 do i:=i-1;
if i=0 and liczby[c,0]=0 then liczby[c,-1]:=0;
else liczby[c,-1]:=i+1;
return p; // reszta z dzielenia
//----------------------------------
// oblicza resztę z dzielenia
function reszta(a,b,r)
local i1;
local i2;
local j1;
local j2;
local f;
begin
przepisz(b,i1);
j1:=13; j2:=14;
przepisz(a,j1);
f:=0;
do
if porownaj(a,i2)>=0 then
begin i1:=i2; if i1=11 then i2:=12; else i2:=11; end;
else f:=1;
// teraz i1<=a ale 10*i1>a
do
do
begin j1:=j2; if j1=13 then j2:=14; else j2:=13; end;
else f:=1;
dziel10(i1,i2);
i1:=i2; if i1=11 then i2:=12; else i2:=11;
// teraz na j1 jest reszta z dzielenia
przepisz(j1,r); end;
//----------------------------------
// główna pętla programu procesora wirtualnego
function testuj()
local i1;
local i2;
begin
i2:=3;
while porownaj(1,i1)>=0 do
begin
if zero(4)=1 then return i1;
dodaj1(i1,2,0,i2);
i1:=i2; if i1=2 then i2:=3; else i2:=2;
return 0;
//----------------------------------
// funkcja przygotowująca do obliczeń (procesor wirtualny)
// i je rozpoczynająca
function przygotuj()
local wynik;
begin
blockread(liczba,liczby[0],34);
// przepisanie zakresów obliczeń
blockread(zakresy[proc],liczby[2],34);
blockread(zakresy[proc+1],liczby[1],34);
// samo obliczenie
wynik:=testuj();
if wynik>0 then blockwrite(liczby[wynik],wyniki[proc],34);
//----------------------------------
// funkcja służąca do ograniczenia przestrzeni przeszukiwanych liczb
function ogranicz(a,c)
local i1;
local i2;
local an;
local cn;
local i;
begin
if i<8 then
cn:=liczby[a,0]+liczby[a,1]*10000;
cn:=sqrt(cn)+1;
liczby[c,0]:=cn%10000;
liczby[c,1]:=cn/10000;
if liczby[c,1]=0 then liczby[c,-1]:=1; else liczby[c,-1]:=2;
if an<10 then i:=i+1;
else if an<100 then i:=i+2;
else if an<1000 then i:=i+3;
else i:=i+4;
i:=i/2+1;
i1:=11; i2:=12;
na_tablice(1,i1);
while i>0 do
begin
i1:=i2; if i1=11 then i2:=12; else i2:=11;
i:=i-1;
razy10(i1,c);
//----------------------------------
// funkcja przygotowująca do obliczeń (serwer)
function rozdziel()
local i1;
local i2;
local k;
begin
ogranicz(0,1);
podziel1(1,proc_number,2);
i1:=3; i2:=4;
na_tablice(3,i1);
blockwrite(liczby[i1],zakresy[0],34);
for k:=1 to proc_number-1 do
begin
i1:=i2; if i1=11 then i2:=12; else i2:=11;
if liczby[i1,0]%2=0 then
begin
i1:=i2; if i1=11 then i2:=12; else i2:=11;
blockwrite(liczby[i1],zakresy[k],34);
blockwrite(liczby[1],zakresy[proc_number],34);
// jeszcze wyzerowanie tablicy wyników
na_tablice(0,5);
for k:=0 to 31 do blockwrite(liczby[5],wyniki[k],34);
//----------------------------------
// część główna programu
begin
if proc_number=0 then exit;
if liczba[0]%2=0 then
begin
blockwrite(liczby[0],wyniki[0],34);
exit;
rozdziel();
for proc:=0 to proc_number-1 pardo przygotuj();