// Catalin Balan
// Mon Mar 29 13:00:55 EEST 2010
// preONI 2004 - atac
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <utility>
#include <bitset>
using namespace std;
#define NMAX 32024
#define CHUNK 8192
#define LogMAX 30
#define FIN "atac.in"
#define FOUT "atac.out"
char g_buf[CHUNK];
int g_p=CHUNK-1;
inline int get()
{
int x = 0;
while (g_buf[g_p] < '0' || g_buf[g_p] > '9')
if (++g_p == CHUNK) fread(g_buf,1,CHUNK,stdin), g_p=0;
while (g_buf[g_p] >= '0' && g_buf[g_p] <= '9')
{
x = x*10 + g_buf[g_p]-'0';
if (++g_p == CHUNK) fread(g_buf,1,CHUNK,stdin), g_p=0;
}
return x;
}
typedef pair<int, int> edg;
vector<edg> G[NMAX];
int nn,m,p;
int LCA[2*NMAX]; // nodurile puse in parcurgerea euleriana
int lvl[2*NMAX]; // adancimile nodurilor in aceeasi parcurgere
int pLCA[NMAX]; // pozitia unui nod in parcurgerea euleriana
int RMQ[2*NMAX][LogMAX]; // RMQ doh... - tin pozitii in lvl, nu valori
bitset<NMAX> viz;
int parents[NMAX][LogMAX]; // parents[i][j] = cine e al 2^j-lea parine al lui i
int costs[NMAX][LogMAX]; // costul desfiintarii drumului intre i si al 2^j-lea parinte al lui i
int n;
// fa parcurgerea euler
void makeLCA( int nod, int &p, int depth)
{
LCA[p] = nod;
lvl[p] = depth;
pLCA[nod] = p;
++p;
viz[nod] = true;
if ( nod != 1 && G[nod].size() == 1) return;
vector<edg>::iterator it;
for (it = G[nod].begin(); it != G[nod].end(); ++it)
{
if (viz[it->first]) continue;
costs[it->first][0] = it->second; // astea 2 linii == initializare la makeCosta();
parents[it->first][0] = nod;
makeLCA( it->first, p, depth+1 );
LCA[p] = nod;
lvl[p] = depth;
++p;
}
}
// precalculeaza range minimum querry pe parcurgerea euler
void makeRMQ( int st, int dr )
{
for (int i = st; i <= dr; ++i)
RMQ[i][0] = i;
for (int len = 1; (1<<len) <= dr; ++len)
{
int len2 = 1<<(len-1);
for (int i = st; i <= dr+1-len; ++i)
{
RMQ[i][len] = RMQ[i][len-1];
if ( lvl[ RMQ[i][len] ] > lvl[ RMQ[i+len2][len-1] ])
RMQ[i][len] = RMQ[i+len2][len-1];
}
}
}
// calculeaza parintii si costurile de oridinul 2^j al fiecarui nod
void makeCosts()
{
parents[0][0] = 0;
costs[0][0] = 200000; // infinit
parents[1][0] = 0;
costs[1][0] = 200000; // infinit
for (int len = 1; (1<<len) < n; ++len )
{
for (int i = 2; i <= n; ++i)
{
parents[i][len] = parents[ parents[i][len-1] ][len-1];
costs[i][len] = min( costs[i][len-1], costs[ parents[i][len-1] ][len-1] );
}
}
}
// afla cel mai apropiat bunic al nodurilor cu pozitiile st, si dr in LCA[]
int queryLCA( int st, int dr )
{
int l = dr-st+1;
int len;
for (len = 1; (1<<len) <= l; ++len);
--len;
// fprintf(stderr, "\n-- %d %d %d %d --\n", st, dr, len, l);
int rez = RMQ[st][len];
if (lvl[ RMQ[st][len] ] > lvl[ RMQ[dr-(1<<len)+1][len] ]) rez = RMQ[dr-(1<<len)+1][len];
return LCA[rez];
}
// afla costul minim de a-l taia pe nodul nod de al nth-lea stramos al sau
int getCost( int nod, int nth )
{
int rez = 200000; // infinit
int len;
for (len = 1; (1<<len) <= nth; ++len);
for (--len; len >= 0; --len)
{
if (nth < (1<<len)) continue;
rez = min(rez, costs[nod][len]);
nod = parents[nod][len];
nth -= (1<<len);
}
return rez;
}
int main(int argv, char ** argc)
{
freopen(FIN, "r", stdin);
freopen(FOUT, "w", stdout);
n = get();
m = get();
p = get();
for (int i = 2; i <= n; ++i)
{
int x = get();
int z = get();
G[x].push_back(make_pair(i,z));
G[i].push_back(make_pair(x,z));
}
nn = 1;
makeLCA(1,nn,1);
--nn;
makeRMQ(1,nn);
makeCosts();
int X,Y,A,B,C,D;
X = get();
Y = get();
A = get();
B = get();
C = get();
D = get();
/* for (int i = 1; i <= nn; ++i) fprintf(stderr, "%d ", LCA[i]);
fprintf(stderr, "\n");
for (int i = 1; i <= nn; ++i) fprintf(stderr, "%d ", lvl[i]);
fprintf(stderr, "\n");
for (int i = 1; i <= n; ++i) fprintf(stderr, "%d ", pLCA[i]);
fprintf(stderr, "\n\n");
for (int len = 0; (1<<len) <= nn; ++len)
{
for (int i = 1; i <= nn; ++i) fprintf(stderr, "%d ", RMQ[i][len]);
fprintf(stderr, "\n");
}
fprintf(stderr, "\n\n");
for (int len = 0; (1<<len) <= n; ++len)
{
for (int i = 1; i <= n; ++i) fprintf(stderr, "%d ", costs[i][len]);
fprintf(stderr, "\n");
}
fprintf(stderr, "\n\n");
*/
int Xp, Yp, Z;
for (int i = 1; i <= m; ++i)
{
if (X == Y)
{
if (i >= m-p+1)
printf("0\n");
Xp = (X*A + Y*B)%n + 1;
Yp = (X*C + Y*D)%n + 1;
Y = Yp; X = Xp;
continue;
}
Xp = X;
Yp = Y;
if (pLCA[Yp] < pLCA[Xp]) { int aux = Xp; Xp = Yp; Yp = aux; }
int tata = queryLCA(pLCA[Xp], pLCA[Yp]); // cine e bunicu
int dt = lvl[pLCA[tata]]; // adancimea bunicului
int dx = lvl[pLCA[Xp]]; // adancimea lui X
int dy = lvl[pLCA[Yp]]; // adancimea lui Y
// fprintf(stderr, "%d %d %d %d - %d %d = %d %d\n", Xp, Yp, dx-dt, dy-dt, tata, dt, getCost(Xp, dx-dt), getCost(Yp, dy-dt));
Z = min( getCost(Xp, dx-dt), getCost(Yp, dy-dt) );
if (i >= m-p+1)
printf("%d\n", Z );
Xp = (X*A + Y*B)%n + 1;
Yp = (Y*C + Z*D)%n + 1;
Y = Yp; X = Xp;
}
return EXIT_SUCCESS;
}