Problem:
Problem J:
The Teacher’s Side of Math
One of the tasks students routinely carry out in their mathematics classes is to solve a polynomial equation. It is, given a polynomial, say
X
2
- 4
X
+ 1, to find its roots (2 ± √3).
If the students’ task is to find the roots of a given polynomial, the teacher’s task is then to find a polynomial that has a given root. Ms. Galsone is an enthusiastic mathematics teacher who is bored with finding solutions of quadratic equations that are as simple as
a
+
b
√
c
. She wanted to make higher-degree equations whose solutions are a little more complicated. As usual in problems in mathematics classes, she wants to maintain all coefficients to be integers and keep the degree of the polynomial as small as possible (provided it has the specified root). Please help her by writing a program that carries out the task of the teacher’s side.
You are given a number t of the form:
t =
m
√
a
+
n
√
b
where
a
and
b
are distinct prime numbers, and
m
and
n
are integers greater than 1.
In this problem, you are asked to find t's
minimal polynomial on integers
, which is the polynomial
F
(
X
) =
a
d
X
d
+
a
d
-1
X
d
-1
+ ... +
a
1
X
+
a
0
satisfying the following conditions.
Coefficients
a
0
, ... ,
a
d
are integers and
a
d
> 0.
F
(
t
) = 0.
The degree
d
is minimum among polynomials satisfying the above two conditions.
F
(
X
) is primitive. That is, coefficients
a
0
, ... ,
a
d
have no common divisors greater than one.
For example, the minimal polynomial of √3+ √2 on integers is
F
(
X
) =
X
4
- 10
X
2
+ 1. Verifying
F
(
t
) = 0 is as simple as the following (
α
= 3,
β
= 2).
F
(
t
) = (
α
+
β
)
4
- 10(
α
+
β
)
2
+ 1
= (
α
4
+ 4
α
3
β
+ 6
α
2
β
2
+ 4
αβ
3
+
β
4
) - 10(
α
2
+ 2
αβ
+
β
2
) + 1
= 9 + 12
αβ
+ 36 + 8
αβ
+ 4 - 10(3 + 2
αβ
+ 2) + 1
= (9 + 36 + 4 - 50 + 1) + (12 + 8 - 20)
αβ
= 0
Verifying that the degree of
F
(
t
) is in fact minimum is a bit more difficult. Fortunately, under
the condition given in this problem, which is that
a
and
b
are distinct prime numbers and
m
and
n
greater than one, the degree of the minimal polynomial is always
mn
. Moreover, it is
always
monic
. That is, the coefficient of its highest-order term (
a
d
) is one.
Input
The input consists of multiple datasets, each in the following format.
a    m   b      n
This line represents
m
√
a
+
n
√
b
. The last dataset is followed by a single line consisting of four zeros. Numbers in a single line are separated by a single space.
Every dataset satisfies the following conditions.
m
√
a
+
n
√
b
≤ 4.
mn
≤ 20.
The coefficients of the answer
a
0
, ... ,
a
d
are between (-2
31
+ 1) and (2
31
- 1), inclusive.
Output
For each dataset, output the coefficients of its minimal polynomial on integers
F
(
X
) =
a
d
X
d
+
a
d
-1
X
d
-1
+ ... +
a
1
X
+
a
0
, in the following format.
a
d
a
d
-1
...
a
1
a
0
Non-negative integers must be printed without a sign (+ or -). Numbers in a single line must
be separated by a single space and no other characters or extra spaces may appear in
...(truncated)

Submitted solutions:

code_snippet: #include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <iomanip>
#include <cassert>

using namespace std;

typedef long long LL;

#define REP(i, n) for (int i(0); i < (int) (n); i++)

void solve() {
}

int f[2][41][41][41];// x ^ i  A ^ y * B ^ z * root ^ k
const long double PI=acos((long double)-1.);

int a,b,m,n;

long double Cos[41][41];
long double Sin[41][41];

int main(){
	for(int i = 1; i <= 40; ++i){
		Cos[i][0] = 1;
		long double t = 2 * PI / i, tmp = 0;
		for(int j = 1; j < i; ++j){
			tmp += t;
			Cos[i][j] = cos(tmp);
			Sin[i][j] = sin(tmp);
		}
	}
	while(scanf("%d%d%d%d",&a,&m,&b,&n)==4&&a){
		memset(f, 0, sizeof(f));
		int n1=0,n2=1;
		f[n1][0][0][0] = 1;
		for(int i = 0; i < m * n; ++i){
			int x = i / n * n;
			int y = i % n * m;// * x - sqrt(a, m) * e ^ x - sqrt(b, n) * e ^ y
			for(int j = 0; j <= i; ++j){
				for(int k = 0; k < n * m; ++k){
					int fx = k / n;
					int fy = k % n;
					for(int l = 0; l < n * m; ++l) if(f[n1][j][k][l]){
						f[n2][j + 1][k][l] += f[n1][j][k][l]; // x
						f[n2][j][(fx + 1 == m ? 0 : fx + 1) * n + fy][l + x >= n * m ? l + x - n * m : l + x] -= f[n1][j][k][l] * (fx + 1 == m ? a : 1);
						f[n2][j][fx * n + (fy + 1 == n ? 0 : fy + 1)][l + y >= n * m ? l + y - n * m : l + y] -= f[n1][j][k][l] * (fy + 1 == n ? b : 1);
						f[n1][j][k][l] = 0;
					}
				}
			}
			swap(n1, n2);
		}
		for(int i = m * n; i >= 0; --i){
//			printf("%d %c",f[n1][i][0][0] - (n * m % 2 == 0 ? f[n1][i][0][n * m / 2] : 0), i == 0 ? '\n' : ' ');
			long double now = 0, che = 0;
			for(int k = 0; k < n * m; ++k){
				now += f[n1][i][0][k] * Cos[n * m][k];
				che += f[n1][i][0][k] * Sin[n * m][k];
			}
			LL v = now + (now<0?-0.5:0.5);
			printf("%d%c",(int)v,i==0?'\n':' ');
//			assert(-1e-6 < che && che < 1e-6);
		}
	}
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 4380
final_rank: 9

code_snippet: #include <bits/stdc++.h>

using namespace std;

typedef long double dbl;

const int MAXNM = 21;
int binom[MAXNM][MAXNM];
const dbl EPS = 1e-10;

void calcbinom() {
    for (int i = 0; i < MAXNM; ++i) {
        binom[i][0] = 1;
        for (int j = 1; j <= i; ++j)
            binom[i][j] = binom[i - 1][j] + binom[i - 1][j - 1];
    }
}

void gauss(vector<vector<dbl>> &a) {
    int n = a.size();
    int m = a[0].size();
    for (int col = 0, row = 0; col < m && row < n; ++col) {
        for (int i = row; i < n; ++i) {
            if (abs(a[i][col]) > EPS) {
                swap(a[i], a[row]);
                break;
            }
        }
        if (abs(a[row][col]) < EPS)
            continue;
        for (int i = 0; i < n; ++i) {
            if (i != row && abs(a[i][col]) > EPS) {
                dbl val = a[i][col] / a[row][col];
                for (int j = col; j < m; ++j) {
                    a[i][j] -= val * a[row][j];
                }
            }
        }
        ++row;
    }
}

vector<dbl> sle(vector<vector<dbl>> a, vector<dbl> b) {
    int n = a.size();
    int m = a[0].size();
    for (int i = 0; i < n; ++i) {
        a[i].push_back(b[i]);
    }
    gauss(a);
    vector<dbl> x(m, 0);
    for (int i = n - 1; i >= 0; --i) {
        int leftmost = m;
        for (int j = 0; j < m; ++j) {
            if (abs(a[i][j]) > EPS) {
                leftmost = j;
                break;
            }
        }
        if (leftmost == m) continue;
        dbl val = a[i].back();
        for (int j = m - 1; j > leftmost; --j) {
            val -= a[i][j] * x[j];
        }
        x[leftmost] = val / a[i][leftmost];
    }
    return x;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    calcbinom();
    while (true) {
        int a, m, b, n;
        cin >> a >> m >> b >> n;
        if (a == 0)
            break;
        vector<vector<dbl>> A(n * m, vector<dbl>(n * m + 1, 0));
        for (int k = 0; k <= n * m; ++k) {
            for (int i = 0; i <= k; ++i) {
                int j = k - i;
                A[(i % m) * n + j % n][k] += binom[k][i] * pow((dbl)a, i / m) * pow((dbl)b, j / n);
            }
        }
        A.emplace_back(n * m + 1, 0);
        A[n * m][n * m] = 1;
        vector<dbl> B(n * m + 1, 0);
        B[n * m] = 1;
        auto X = sle(A, B);
        vector<int> res(n * m + 1);
        for (int i = 0; i <= n * m; ++i)
            res[i] = round(X[i]);

        for (int i = n * m; i >= 0; --i) {
            cout << res[i];
            if (i)
                cout << ' ';
        }
        cout << '\n';
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3576
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;

using LL=__int128_t;

LL mod;
ll nCk[21][21];

void init(){
    for(int i=0;i<21;i++)nCk[i][0]=1;
    for(int i=0;i<21;i++){
        for(int j=1;j<=i;j++){
            nCk[i][j]=nCk[i-1][j-1]+nCk[i-1][j];
        }
    }
    while(1){
        mod=1e10+rand()%100000;
        bool OK=1;
        for(ll p=2;p*p<=mod;p++){
            if(mod%p==0){
                OK=0;
                break;
            }
        }
        if(OK)return;
    }
}

LL pow(LL a,LL n){
    a%=mod;
    if(n==0)return 1;
    if(n%2)return (pow(a,n-1)*a)%mod;
    LL t=pow(a,n/2);
    return (t*t)%mod;
}
LL inv(LL a){return pow(a,mod-2);}

// AX=Y
// A is square mat
vector<LL> LE(vector<vector<LL>> A,vector<LL> Y){
    int n=A.size();
    for(int i=0;i<n;i++){
        for(int j=i;j<n;j++){
            if(A[j][i]!=0){
                swap(A[i],A[j]);
                swap(Y[i],Y[j]);
                break;
            }
        }
        LL d=inv(A[i][i]);
        for(int j=0;j<n;j++)A[i][j]=(A[i][j]*d)%mod;
        Y[i]=(Y[i]*d)%mod;
        for(int k=0;k<n;k++){
            if(i==k)continue;
            LL v=A[k][i];
            for(int j=0;j<n;j++){
                A[k][j]=(A[k][j]-(v*A[i][j])%mod)%mod;
                if(A[k][j]<0)A[k][j]+=mod;
            }
            Y[k]=(Y[k]-(v*Y[i])%mod)%mod;
            if(Y[k]<0)Y[k]+=mod;
        }
    }
    for(auto &y:Y)if(y>(1ll<<31)+1)y-=mod;
    return Y;
}



vector<LL> pow(ll A,ll M,ll B,ll N,ll K){
    vector<LL> R(M*N);
    //(m,n)<->a*N+n
    for(int i=0;i<=K;i++){
        //A^(i/M)*B^((K-i))/M;
        int m=i%M;
        int n=(K-i)%N;
        LL u=nCk[K][i];
        for(int j=0;j<i/M;j++)u=(u*A)%mod;
        for(int j=0;j<(K-i)/N;j++)u=(u*B)%mod;
        R[m*N+n]+=u;
        R[m*N+n]%=mod;
    }
    return R;
}
ll A,M,B,N;
void solve(){
    int n=M*N;
    vector<vector<LL>> MT(n,vector<LL>(n));
    vector<LL> Y(n);
    vector<LL> D;
    for(int i=0;i<n;i++){
        D=pow(A,M,B,N,i);
        for(int k=0;k<n;k++){
            MT[n-1-k][n-1-i]=D[k];
        }
    }
    D=pow(A,M,B,N,n);
    for(int k=0;k<n;k++){
        Y[n-1-k]=-D[k];
    }
    Y=LE(MT,Y);
    cout<<1;
    for(int i=0;i<n;i++)cout<<" "<<ll(Y[i]);
    cout<<endl;
}


int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);


    init();
    while(cin>>A>>M>>B>>N,A!=0)solve();
    

}
accuracy: 1
time_ms: 60
memory_kb: 3420
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
vector<int> mobius = {0, 1, -1, -1, 0, -1, 1, -1, 0, 0, 1};
int main(){
  while (true){
    int a, m, b, n;
    cin >> a >> m >> b >> n;
    if (a == 0 && m == 0 && b == 0 && n == 0){
      break;
    }
    int d = m * n;
    vector<vector<vector<vector<vector<vector<unsigned int>>>>>> dp(d + 1, vector<vector<vector<vector<vector<unsigned int>>>>>(d + 1, vector<vector<vector<vector<unsigned int>>>>(m, vector<vector<vector<unsigned int>>>(m, vector<vector<unsigned int>>(n, vector<unsigned int>(n, 0))))));
    dp[0][0][0][0][0][0] = 1;
    for (int i = 0; i < d; i++){
      int da = i / n;
      int db = i % n;
      for (int j = 0; j <= i; j++){
        for (int d1 = 0; d1 < m; d1++){
          for (int d2 = 0; d2 < m; d2++){
            for (int d3 = 0; d3 < n; d3++){
              for (int d4 = 0; d4 < n; d4++){
                dp[i + 1][j + 1][d1][d2][d3][d4] += dp[i][j][d1][d2][d3][d4];
                if (d1 < m - 1){
                  dp[i + 1][j][d1 + 1][(d2 + da) % m][d3][d4] -= dp[i][j][d1][d2][d3][d4];
                } else {
                  dp[i + 1][j][0][(d2 + da) % m][d3][d4] -= dp[i][j][d1][d2][d3][d4] * a;
                }
                if (d3 < n - 1){
                  dp[i + 1][j][d1][d2][d3 + 1][(d4 + db) % n] -= dp[i][j][d1][d2][d3][d4];
                } else {
                  dp[i + 1][j][d1][d2][0][(d4 + db) % n] -= dp[i][j][d1][d2][d3][d4] * b;
                }
              }
            }
          }
        }
      }
    }
    vector<unsigned int> ans(d + 1, 0);
    for (int i = 0; i <= d; i++){
      for (int j = 1; j <= m; j++){
        for (int k = 1; k <= n; k++){
          if (m % j == 0 && n % k == 0){
            ans[i] += dp[d][i][0][m / j % m][0][n / k % n] * mobius[j] * mobius[k];
          }
        }
      }
    }
    reverse(ans.begin(), ans.end());
    for (int i = 0; i <= d; i++){
    	if (ans[i] >= 2147483648){
    	  ans[i] = -ans[i];
    	  cout << '-';
    	}
      cout << ans[i];
      if (i < d){
        cout << ' ';
      }
    }
    cout << endl;
  }
}
accuracy: 1
time_ms: 540
memory_kb: 10400
final_rank: 10

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld=long double;

/* verified AOJ1327 One-Dimensional Cellular Automaton
~Matrix~
行列の簡単な計算ができる
vector iostream cmath cassert 必須
Matrix a(VV), b(VV);
行列式:a*b
スカラ積:l*a
和:a+b
差:a-b
転置:a.transport()
余因子:a.cofactor()
行列式:a.det()
aのi行j列目:a.get(i,j)　
aのi行目j列目にkを代入:set(i,j,k)
もしくはa[i][j] (a[i][j]=k)
aのx乗:a.pow(x)
n*n基本行列E:Matrix(n)
m*n 0行列:Matrix(m,n)
m*n 全要素がpの行列:Matrix(m,n,p)
Row型rowでの初期化(m*1行列):Matrix(row)
**(整数不可)**
三角化:a.triangulate()
ランク:a.rank()
逆行列:a.inverse()
//(逆行列のa.det()倍ならa.pre_inverse()で求まる 整数可)
ガウスの消去法:a.rowReduction()
//連立一次方程式が解ける
***
*/

#include <vector>
#include <iostream>
#include <cmath>
#include <cassert>
using namespace std;

typedef ld Elem;
typedef vector<Elem> Row;
typedef vector<Row> VV;

typedef long double ld;
const ld EPS = 1e-11;

const bool isZero(const Elem e) {
	return abs(e) < EPS;
}

struct Matrix {
	VV matrix;
	int n, m;

	Matrix(const VV &matrix_);
	explicit Matrix(int n_);
	explicit Matrix(const Row &row);
	Matrix(int m_, int n_);
	Matrix(int m_, int n_, Elem e);

	const Elem get(const int i, const int j) const;
	void set(const int x, const int y, const Elem k);

	const Matrix operator + (const Matrix &rhs) const;
	const Matrix operator * (const Matrix &rhs) const;
	const Matrix operator - (const Matrix &rhs) const;
	Matrix &operator += (const Matrix &rhs);
	Matrix &operator *= (const Matrix &rhs);
	Matrix &operator -= (const Matrix &rhs);

	Row &operator[](const int x);

	const Matrix transport() const;
	const Matrix pow(int x) const;
	const Matrix cofactor(int x, int y) const;
	const Elem det() const;

	const Matrix triangulate() const;
	const int rank() const;

	//逆行列が存在すれば、(行列式)*(逆行列)を返す
	//A:matrix,return det A * A^-1
	const Matrix pre_inverse() const;
	const Matrix inverse() const;
	const Matrix rowReduction() const;
};

const Matrix operator * (const Elem lambda, const Matrix &rhs) {
	Matrix tmp(rhs);
	for (int i = 0; i < rhs.m; i++)
		for (int j = 0; j < rhs.n; j++)
			tmp.set(i, j, tmp.get(i, j) * lambda);
	return tmp;
}

Matrix::Matrix(const VV &matrix_) : matrix(matrix_) {
	m = matrix_.size();
	if (m == 0) n = 0;
	else n = matrix_[0].size();
}
Matrix::Matrix(int n_) : m(n_), n(n_) {
	matrix = VV(n, Row(n, 0));
	for (int i = 0; i < n; ++i)
		set(i, i, 1);
}
Matrix::Matrix(const Row &row) : m(1), n(row.size()), matrix(VV(1, row)) {
	//sizeがmのvector<Elem>からmx1行列の生成
	(*this) = transport();
}
Matrix::Matrix(int m_, int n_) : m(m_), n(n_) {
	matrix = VV(m, Row(n, 0));
}
Matrix::Matrix(int m_, int n_, Elem e) : m(m_), n(n_) {
	matrix = VV(m, Row(n, e));
}

const Elem Matrix::get(const int i, const int j) const {
	if (0 <= i && i < m && 0 <= j && j < n)
		return matrix[i][j];

	cerr << "get(" << i << "," << j << ")is not exist." << endl;
	throw;
}
void Matrix::set(const int i, const int j, const Elem k) {
	if (0 <= i && i < m && 0 <= j && j < n) {
		*(matrix[i].begin() + j) = k;
		return;
	}
	cerr << "set(" << i << "," << j << ")is not exist." << endl;
	throw;
}

const Matrix Matrix::operator + (const Matrix &rhs) const {
	assert(m == rhs.m && n == rhs.n);

	Matrix tmp(m, n, 0);
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			tmp.set(i, j, get(i, j) + rhs.get(i, j));
		}
	}
	return tmp;
}

const Matrix Matrix::operator * (const Matrix &rhs) const {
	assert(n == rhs.m);

	Matrix tmp(m, rhs.n, 0);
	Elem sum;
	for (int i = 0; i < m; i++)
		for (int j = 0; j < rhs.n; j++) {
			sum = 0;
			for (int k = 0; k < n; k++) {
				sum += get(i, k) * rhs.get(k, j);
			}
			tmp.set(i, j, sum);
		}
	return tmp;
}

const Matrix Matrix::operator - (const Matrix &rhs) const {
	return *this + ((Elem)-1 * rhs);
}

Matrix &Matrix::operator += (const Matrix &rhs) {
	return *this = *this + rhs;
}

Matrix &Matrix::operator *= (const Matrix &rhs) {
	return *this = *this * rhs;;
}

Matrix &Matrix::operator -= (const Matrix &rhs) {
	return *this = *this - rhs;
}

Row &Matrix::operator[](const int x) {
	return matrix[x];
}

const Matrix Matrix::transport() const {
	VV tmp;
	for (int i = 0; i < n; i++) {
		Row row;
		for (int j = 0; j < m; j++)
			row.push_back(get(j, i));
		tmp.push_back(row);
	}
	return tmp;
}

const Matrix Matrix::pow(int x) const {
	Matrix tmp(*this), e(m);
	for (int i = 1; i <= x; i <<= 1) {
		if ((x & i) > 0)
			e = e * tmp;
		tmp = tmp * tmp;
	}
	return e;
}

const Matrix Matrix::cofactor(int x, int y) const {
	VV tmp;
	for (int i = 0; i < m; i++) {
		if (x == i) continue;
		Row row;
		for (int j = 0; j < n; j++) {
			if (y == j) continue;
			row.push_back(get(i, j));
		}
		tmp.push_back(row);
	}
	return Matrix(tmp);
}

const Elem Matrix::det() const {
	assert(n == m);
Matrix tri = triangulate();
Elem ans = 1;
for (int i = 0; i < n; ++i) {
	ans *= tri[i][i];
}
return ans;

	if (m == 1)
		return get(0, 0);
	Elem sum = 0;
	for (int i = 0; i < m; i++) {
		sum += ((i % 2 == 0 ? 1 : -1) * get(i, 0)) * Matrix(cofactor(i, 0)).det();
	}
	return sum;
}

const Matrix Matrix::triangulate() const {
	Matrix tmp(*this);
	Elem e;
	int p = 0;
	for (int i = 0; i < m && p < n; i++, p++) {
		if (isZero(tmp.get(i, p))) {
			tmp.set(i, p, 0);
			bool flag = true;
			for (int j = i + 1; j < m; j++)
				if (!isZero(tmp.get(j, p))) {
					for (int k = 0; k < n; k++)
						tmp.set(i, k, tmp.get(i, k) + tmp.get(j, k));
					//tmp[i].swap(tmp[j]);
					flag = false;
					break;
				}
			if (flag) {
				i--;
				continue;
			}
		}
		for (int j = i + 1; j < m; j++) {
			e = tmp.get(j, p) / tmp.get(i, p);
			for (int k = 0; k < n; k++)
				tmp.set(j, k, tmp.get(j, k) - tmp.get(i, k) * e);
		}
	}
	return tmp;
}

const int Matrix::rank() const {
	Matrix tmp(triangulate());
	for (int i = min(tmp.m - 1, tmp.n - 1); i >= 0; i--) {
		for (int j = tmp.n - 1; j >= i; j--)
			if (isZero(tmp.get(i, j)))
				continue;
			else
				return i + 1;
	}
	return 0;
}

const Matrix Matrix::pre_inverse() const {
	assert(m == n);

	Matrix tmp(m, n, 0);
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			tmp.set(i, j, ((i + j) % 2 == 0 ? 1 : -1)*cofactor(i, j).det());
	return tmp.transport();
}

/*O(n!)実装
const Matrix Matrix::inverse() const {
Matrix tmp(pre_inverse());
Elem e = det();
assert(!isZero(e));
tmp = 1 / e * tmp;
return tmp.transport();
}*/

const Matrix Matrix::inverse() const {
	assert(m == n);

	Matrix tmp(m, n * 2), tmp2(m, n);
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			tmp.set(i, j, get(i, j));
	for (int i = 0; i < m; i++)
		tmp.set(i, i + n, 1);

	tmp = tmp.rowReduction();

	//逆行列が存在するかどうかのチェック
	for (int i = 0; i < m; i++)
		assert(isZero(tmp.get(i, i) - 1));

	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			tmp2.set(i, j, tmp.get(i, j + n));

	return tmp2;
}

/*
a b c j
d e f k
g h i l

ax+by+cz=j;
dx+ey+fz=k;
gx+hy+iz=l;

|
V

1 0 0 x
0 1 0 y
0 0 1 z
右端が答え
*/
const Matrix Matrix::rowReduction() const {
	Matrix tmp(*this);
	Elem e;
	int p = 0;
	for (int i = 0; i < m && p < n; i++, p++) {
		if (isZero(tmp.get(i, p))) {
			tmp.set(i, p, 0);
			bool flag = true;
			for (int j = i + 1; j < m; j++)
				if (!isZero(tmp.get(j, p))) {
					for (int k = 0; k < n; k++)
						tmp.set(i, k, tmp.get(i, k) + tmp.get(j, k));
					//tmp[i].swap(tmp[j]);
					flag = false;
					break;
				}
			if (flag) {
				i--;
				continue;
			}
		}
		e = 1 / tmp.get(i, p);
		tmp.set(i, p, 1);
		for (int k = i + 1; k < n; k++)
			tmp.set(i, k, tmp.get(i, k)*e);
		for (int j = 0; j < m; j++) {
			if (i == j) continue;
			e = tmp.get(j, p);
			for (int k = 0; k < n; k++)
				tmp.set(j, k, tmp.get(j, k) - tmp.get(i, k) * e);
		}
	}
	return tmp;
}

int main()
{
	while (true) {
		//m√a + n√b ≤ 4

		int A, M, B, N; cin >> A >> M >> B >> N;
		if(!A)break;
		vector<vector<vector<ld>>>nums(M*N + 1, vector<vector<ld>>(M, vector<ld>(N)));
		nums[0][0][0] = 1;

		for (int i = 0; i < M*N; ++i) {
			for (int a = 0; a < M; ++a) {
				for (int b = 0; b < N; ++b) {
					{

						ld bai = b == N - 1 ? B : 1;
						nums[i + 1][a][(b + 1) % N] += bai*nums[i][a][b];
					}
					{
						ld bai = a == M - 1 ? A : 1;
						nums[i + 1][(a + 1) % M][b] += bai*nums[i][a][b];
					}
				}
			}
		}
		Matrix mat(M*N + 1, M*N + 2);
		for (int a = 0; a < M; ++a) {
			for (int b = 0; b < N; ++b) {
				for (int i = 0; i <= M*N; ++i) {
					mat[a*N + b][i] = nums[i][a][b];
				}
				mat[a*N + b][M*N + 1] = 0;
			}
		}
		mat[M*N][M*N] = 1;
		mat[M*N][M*N + 1] = 1;

		auto ans = mat.rowReduction();

		vector<long long int>anss(M*N+1);
		for(int x=0;x<=M*N;++x){
			anss[x]=round(ans[x][M*N+1]);
		}
		for (int i = 0; i <= M*N; ++i) {
			cout<<anss[M*N-i];
			if(i==M*N)cout<<endl;
			else cout<<" ";
		}
	}
	
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3332
final_rank: 7

code_snippet: #include <vector>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;

bool gauss(vector<vector<long double> > &a){
	if(a.empty())return false;
	int n=a.size();
	for(int i=0;i<n;i++){
		if(!a[i][i]){
			int j=i+1;
			for(;j<n;j++){
				if(a[j][i]){
					for(int k=i;k<=n;k++)a[i][k]+=a[j][k];
					break;
				}
			}
			if(j==n)return false;
		}
		for(int j=0;j<n;j++)if(i!=j){
			long double r=a[j][i]/a[i][i];
			for(int k=i;k<=n;k++)a[j][k]=a[j][k]-a[i][k]*r;
		}
	}
	for(int i=0;i<n;i++){
		long double x=a[i][i];
		for(int j=0;j<a[i].size();j++)a[i][j]/=x;
	}
	return true;
}
long long comb(int n,int k){
	if(k>n-k)k=n-k;
	long long r=1;
	for(int i=0;i<k;i++)r=r*(n-i)/(i+1);
	return r;
}
long long pow_binary(long long x,long long y){
	long long z=1;
	for(;y;y>>=1){
		if((y&1)!=0)z=z*x;
		x=x*x;
	}
	return z;
}
int main(){
	int A,M,B,N;
	for(;scanf("%d%d%d%d",&A,&M,&B,&N),A;){
		vector<vector<long double> >m(M*N+1);
		for(int i=0;i<=M*N;i++)m[i].resize(M*N+2);
		m[0][0]=m[0][M*N+1]=1;
		for(int i=0;i<=M*N;i++)for(int k=0;k<=i;k++){
			m[k%M*N+(i-k)%N+1][i<M*N ? i+1 : 0]+=(long double)comb(i,k)*pow_binary(A,k/M)*pow_binary(B,(i-k)/N);
		}
		gauss(m);
		printf("1");
		for(int i=M*N;i>0;i--)printf(" %d",(int)(roundl(m[i][M*N+1])));
		puts("");
	}
}
accuracy: 1
time_ms: 10
memory_kb: 1064
final_rank: 2

code_snippet: #include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
using namespace std;
const double EPS=1e-8;
typedef vector<double>vec;
typedef vector<vec>mat;
double ABS(double a){return max(a,-a);}
vec gauss_jordan(const mat &A,const vec &b){
	int n=A.size();
	mat B(n,vec(n+1));
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)B[i][j]=A[i][j];
	for(int i=0;i<n;i++)B[i][n]=b[i];
	for(int i=0;i<n;i++){
		int pivot=i;
		for(int j=i;j<n;j++){
			if(ABS(B[j][i])>ABS(B[pivot][i]))pivot=j;
		}
		swap(B[i],B[pivot]);
		if(ABS(B[i][i])<EPS)return vec();
		for(int j=i+1;j<=n;j++)B[i][j]/=B[i][i];
		for(int j=0;j<n;j++){
			if(i!=j){
				for(int k=i+1;k<=n;k++)B[j][k]-=B[j][i]*B[i][k];
			}
		}
	}
	vec x(n);
	for(int i=0;i<n;i++)x[i]=B[i][n];
	return x;
}
double now[30][30][30];
int main(){
	int a,m,b,n;
	while(scanf("%d%d%d%d",&a,&m,&b,&n),a){
		for(int i=0;i<30;i++)for(int j=0;j<30;j++)for(int k=0;k<30;k++)
			now[i][j][k]=0;
		now[0][0][0]=1;
		for(int i=0;i<m*n;i++){
			for(int j=0;j<m;j++){
				for(int k=0;k<n;k++){
					now[i+1][j+1][k]+=now[i][j][k];
					now[i+1][j][k+1]+=now[i][j][k];
				}
			}
			for(int j=0;j<n;j++)now[i+1][0][j]+=now[i+1][m][j]*a;
			for(int j=0;j<m;j++)now[i+1][j][0]+=now[i+1][j][n]*b;
			now[i+1][0][0]+=now[i+1][m][n]*a*b;
		}
		mat A(m*n,vec(m*n));
		vec B(m*n);
		for(int i=0;i<m*n;i++){
			for(int j=0;j<m;j++){
				for(int k=0;k<n;k++){
					A[j*n+k][i]=now[i][j][k];
				}
			}
		}
		for(int i=0;i<m;i++)for(int j=0;j<n;j++)
			B[i*n+j]-=now[n*m][i][j];
		vec x=gauss_jordan(A,B);
		printf("1");
		for(int i=m*n-1;i>=0;i--){
			printf(" %d",(int)(round(x[i])));
		}
		printf("\n");
	}
}
accuracy: 1
time_ms: 20
memory_kb: 1292
final_rank: 4

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <functional>
using namespace std;
#define rep(i,n) for(int i=0;i<(n);++i)
#define rep1(i,n) for(int i=1;i<=(n);++i)
#define all(c) (c).begin(),(c).end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << x << endl
typedef long long ll;
typedef vector<ll> poly;
ll C[11][11];
poly operator+(poly x,poly y){
	poly ret(21,0);
	rep(i,21){
		ret[i]=x[i]+y[i];
	}
	return ret;
}
poly operator-(poly x,poly y){
	poly ret(21,0);
	rep(i,21){
		ret[i]=x[i]-y[i];
	}
	return ret;
}
poly operator*(poly x,poly y){
	poly ret(21,0);
	rep(i,21) rep(j,21){
		if(i+j>20) continue;
		ret[i+j]+=x[i]*y[j];
	}
	return ret;
}
poly operator*(ll x,poly y){
	poly ret(21,0);
	rep(i,21){
		ret[i]=x*y[i];
	}
	return ret;
}
void Answer(poly p){
	int w=0;
	for(int i=20;i>=0;i--){
		if(w!=0||p[i]!=0){
			if(w==0){
				if(p[i]==1) w=1;
				else w=-1;
			}
			cout<<p[i]*w;
			if(i==0) cout<<endl;
			else cout<<" ";
		}
	}
}
int main(){
	rep(i,11){
		C[i][0]=C[i][i]=1;
		for(int j=1;j<i;j++) C[i][j]=C[i-1][j-1]+C[i-1][j];
	}
	while(true){
		ll a,m,b,n;
		cin>>a>>m>>b>>n;
		if(m==0) break;
		if(m>n) swap(m,n),swap(a,b);
		poly co[4];
		rep(i,4) co[i].assign(21,0);
		if(m==4){
			co[0][0]=-b;
			ll now=1;
			rep(i,n+1){
				co[i%4][n-i]+=C[n][i]*now*(i%2==0 ? 1 : -1);
				if(i%4==3) now*=a;
			}
			poly p=co[3],q=co[2],r=co[1],s=co[0];
			poly ans=a*a*a*p*p*p*p+a*a*(-4*p*p*q*s-2*p*p*r*r+4*p*q*q*r-q*q*q*q)+a*((4*p*r+2*q*q)*s*s-4*q*r*r*s+r*r*r*r)-s*s*s*s;
			Answer(ans);
		}else if(m==3){
			co[0][0]=-b;
			ll now=1;
			rep(i,n+1){
				co[i%3][n-i]+=C[n][i]*now*(i%2==0 ? 1 : -1);
				if(i%3==2) now*=a;
			}
			poly p=co[2],q=co[1],r=co[0];
			poly ans=a*a*p*p*p+a*(q*q*q-3*p*q*r)+r*r*r;
			Answer(ans);
		}else if(m==2){
			co[0][0]=-b;
			ll now=1;
			rep(i,n+1){
				co[i%2][n-i]+=C[n][i]*now*(i%2==0 ? 1 : -1);
				if(i%2==1) now*=a;
			}
			poly p=co[1],q=co[0];
			poly ans=a*p*p-q*q;
			Answer(ans);
		}
	}
}
accuracy: 1
time_ms: 10
memory_kb: 1244
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#include <iostream>
#include <vector>
#include <complex>
#include <algorithm>
#include <cstring>
#include <map>
#include <set>
#include <cstdio>
#include <queue>
#include <cmath>
#include <cstdlib>

using namespace std;
typedef long long ll;
typedef ll li;
typedef pair<int,int> PI;
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define REP(i, n) rep (i, n)
#define F first
#define S second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define SZ(a) (int)((a).size())
#define ALL(a) (a).begin(),(a).end()
#define FLL(a,b) memset((a),b,sizeof(a))
#define CLR(a) memset((a),0,sizeof(a))
#define FOR(it,a) for(__typeof(a.begin())it=a.begin();it!=a.end();++it)
#define FORR(it,a) for(__typeof(a.rbegin())it=a.rbegin();it!=a.rend();++it)
template<typename T,typename U> ostream& operator<< (ostream& out, const pair<T,U>& val){return out << "(" << val.F << ", " << val.S << ")";}
template<class T> ostream& operator<< (ostream& out, const vector<T>& val){out << "{";rep(i,SZ(val)) out << (i?", ":"") << val[i];return out << "}";}
#define EPS (1e-6)
#define declare(a,it) __typeof(a) it=a

typedef vector<long double> arr;
typedef vector<arr> mat;

arr sol(mat A,arr y){//Ax=y, return x
  int n = A.size();
  mat B(n,arr(n));
  for(int i = 0; i < n; ++i)
    B[i][i] = 1;
  
  for(int i = 0; i < n; ++i){
    for(int j=i+1;j < n; ++j){
      if(abs(A[j][i]) > abs(A[i][i])){
         swap(A[j],A[i]);
         swap(B[j],B[i]);
      }
    }
    long double d = A[i][i];
    for(int j = 0; j < n; ++j){
      A[i][j] /= d;
      B[i][j] /= d;
    }

    for(int j = 0; j < n; ++j){
      if(i==j) continue;
      long double m = A[j][i];
      for(int k = 0; k < n; ++k){
        A[j][k] -= A[i][k] * m;
        B[j][k] -= B[i][k] * m;
      }
    }
  }
  
  arr ret(n);
  for(int i = 0; i < n; ++i)
    for(int j = 0; j < n; ++j)
      ret[i] += B[i][j] * y[j];
  
  return ret;
}

int main()
{
  int a,m,b,n;
  while(cin >> a >> m >> b >> n && a){
    arr p(n*m);
    p[0] = 1;
    mat A(n*m,arr(n*m));
    for(int i = n*m-1; i >= 0; --i){
      for(int j = 0; j < n*m; ++j)
        A[j][i] = p[j];
      arr np(n*m);
      for(int j = 0; j < n*m; ++j){
        int an = j % m;
        int bn = j / m;
        long pp = p[j];
        if(an == m-1) np[bn*m] += pp * a;
        else np[bn*m+an+1] += pp;
        
        if(bn == n-1) np[an] += pp * b;
        else np[(bn+1)*m+an] += pp;
      }
      p = np;
    }
    for(auto & i : p) i = -i;
    auto ans = sol(A, p);
    cout << 1;
    for(auto p : ans) printf(" %.0Lf", abs(p)<EPS?0.0:p);
    cout << endl;
  }
}
accuracy: 1
time_ms: 20
memory_kb: 1300
final_rank: 5

code_snippet: #include<cmath>
#include<cstdio>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const long double EPS=1e-9;

const int N_MAX=20;
bool Gauss_Jordan(int n,const long double A[N_MAX][N_MAX],const long double *b,long double *x){
	static long double B[N_MAX][N_MAX+1];
	rep(i,n){
		rep(j,n) B[i][j]=A[i][j];
		B[i][n]=b[i];
	}

	rep(i,n){
		int piv=i;
		for(int j=i;j<n;j++) if(abs(B[j][i])>abs(B[piv][i])) piv=j;
		rep(j,n+1) swap(B[i][j],B[piv][j]);

		if(abs(B[i][i])<EPS) return false;

		for(int j=i+1;j<=n;j++) B[i][j]/=B[i][i];
		rep(j,n) if(i!=j) for(int k=i+1;k<=n;k++) B[j][k]-=B[j][i]*B[i][k];
	}

	rep(i,n) x[i]=B[i][n];
	return true;
}

int main(){
	for(int a,m,b,n;scanf("%d%d%d%d",&a,&m,&b,&n),a;){
		long double coe[21][20][20]={}; // coe[k][i][j] := (^mãa+^nãb)^k Ì ^mã(a^i)*^nã(b^j) ÌW
		coe[0][0][0]=1;
		rep(k,m*n){
			rep(i,m) rep(j,n) {
				if(i<m-1) coe[k+1][i+1][j]+=coe[k][i][j];
				else      coe[k+1][0][j]+=a*coe[k][i][j];
				if(j<n-1) coe[k+1][i][j+1]+=coe[k][i][j];
				else      coe[k+1][i][0]+=b*coe[k][i][j];
			}
		}

		long double A[20][20],x[20],b[20];
		rep(i,m) rep(j,n) {
			b[i*n+j]=-coe[m*n][i][j];
			rep(k,m*n) A[i*n+j][k]=coe[k][i][j];
		}
		Gauss_Jordan(m*n,A,b,x);

		printf("1 ");
		rep(k,m*n) printf("%.0Lf%c",x[m*n-k-1]+EPS,k<m*n-1?' ':'\n');
	}

	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1