#include <iostream>
#include <fstream>
#include <vector>
//#define __DEBUG
std::vector<int> a, b, c;
struct Node {
Node* left, *right;
int span;
int filled;
int color; // Only filled in if homogenous.
Node(Node* left, Node* right, int span, int filled)
: left(left), right(right), span(span), filled(filled), color(0) {}
};
Node* make_tree(int li, int lf) {
if (li == lf) {
return new Node(NULL, NULL, lf - li + 1, 0);
} else {
return new Node(make_tree(li, (li + lf) / 2),
make_tree(((li + lf) / 2) + 1, lf),
lf - li + 1,
0);
}
}
void color_tree(Node* root, int li, int lf, int a, int b, int c) {
#ifdef __DEBUG
std::cerr << "Coloring node (" << li << ", " << lf << ") with interval "
<< "(" << a << ", " << b << "), and color <" << c << ">." << std::endl;
#endif
int m = (li + lf) / 2;
if (a > li || b < lf) {
// Check that (a, b) is strictly included in (li, lf).
if (a <= m) {
#ifdef __DEBUG
std::cerr << "Recursing on left." << std::endl;
#endif
color_tree(root->left, li, m, a, std::min(b, m), c);
}
if (b >= m + 1) {
#ifdef __DEBUG
std::cerr << "Recursing on right." << std::endl;
#endif
color_tree(root->right, m + 1, lf, std::max(a, m + 1), b, c);
}
root->filled = root->left->filled + root->right->filled;
return;
}
// Now we know that (a == li, b == lf).
if (root->filled == root->span) {
// Give up if there is nothing to color.
#ifdef __DEBUG
std::cerr << "Already colored." << std::endl;
#endif
return;
} else if (root->filled == 0) {
#ifdef __DEBUG
std::cerr << "Coloring with <" << c << ">." << std::endl;
#endif
// Color everything if the root is empty.
root->color = c;
root->filled = root->span;
return;
} else {
#ifdef __DEBUG
std::cerr << "Breaking up the coloring because it's patchy." << std::endl;
#endif
color_tree(root->left, li, m, a, m, c);
color_tree(root->right, m + 1, lf, m + 1, b, c);
root->filled = root->left->filled + root->right->filled;
return;
}
}
void flatten_tree(Node* root, int li, int lf, std::ostream& out)
{
if (root->color != 0 || root->filled == 0) {
// If it's either a color, or the root is empty, then print the color.
for (int i = li; i <= lf; ++i) {
out << root->color << std::endl;
}
} else {
// If color is 0 and root is not filled, break it up.
flatten_tree(root->left, li, (li + lf) / 2, out);
flatten_tree(root->right, (li + lf) / 2 + 1, lf, out);
}
}
int main()
{
std::ifstream in("curcubeu.in");
int n, a1, b1, c1;
in >> n >> a1 >> b1 >> c1;
in.close();
a.push_back(std::min(a1, b1));
b.push_back(std::max(a1, b1));
c.push_back(c1);
for (int i = 2; i < n; ++i) {
a1 = (1LL * a1 * i) % n;
b1 = (1LL * b1 * i) % n;
c1 = (1LL * c1 * i) % n;
a.push_back(std::min(a1, b1));
b.push_back(std::max(a1, b1));
c.push_back(c1);
}
Node* root = make_tree(1, n - 1);
for (int i = c.size() - 1; i >= 0; --i) {
color_tree(root, 1, n - 1, a[i], b[i], c[i]);
}
std::ofstream out("curcubeu.out");
// flatten_tree(root, 1, n - 1, out);
out.close();
return 0;
}