Problem:
Score : 2100 points

Problem Statement

We have a rectangular parallelepiped of dimensions A×B×C, divided into 1×1×1 small cubes.
The small cubes have coordinates from (0, 0, 0) through (A-1, B-1, C-1).

Let p, q and r be integers. Consider the following set of abc small cubes:

\{(\ (p + i) mod A, (q + j) mod B, (r + k) mod C\ ) | i, j and k are integers satisfying 0 ≤ i < a, 0 ≤ j < b, 0 ≤ k < c \}

A set of small cubes that can be expressed in the above format using some integers p, q and r, is called a torus cuboid of size a×b×c.

Find the number of the sets of torus cuboids of size a×b×c that satisfy the following condition, modulo 10^9+7:

No two torus cuboids in the set have intersection.

The union of all torus cuboids in the set is the whole rectangular parallelepiped of dimensions A×B×C.

Constraints

1 ≤ a < A ≤ 100

1 ≤ b < B ≤ 100

1 ≤ c < C ≤ 100

All input values are integers.

Input

Input is given from Standard Input in the following format:

a b c A B C

Output

Print the number of the sets of torus cuboids of size a×b×c that satisfy the condition, modulo 10^9+7.

Sample Input 1

1 1 1 2 2 2

Sample Output 1

1

Sample Input 2

2 2 2 4 4 4

Sample Output 2

744

Sample Input 3

2 3 4 6 7 8

Sample Output 3

0

Sample Input 4

2 3 4 98 99 100

Sample Output 4

471975164

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;


template <int MOD_> struct modnum {
	static constexpr int MOD = MOD_;
	static_assert(MOD_ > 0, "MOD must be positive");

private:
	using ll = long long;

	int v;

	static int minv(int a, int m) {
		a %= m;
		assert(a);
		return a == 1 ? 1 : int(m - ll(minv(m, a)) * ll(m) / a);
	}

public:

	modnum() : v(0) {}
	modnum(ll v_) : v(int(v_ % MOD)) { if (v < 0) v += MOD; }
	explicit operator int() const { return v; }
	friend std::ostream& operator << (std::ostream& out, const modnum& n) { return out << int(n); }
	friend std::istream& operator >> (std::istream& in, modnum& n) { ll v_; in >> v_; n = modnum(v_); return in; }

	friend bool operator == (const modnum& a, const modnum& b) { return a.v == b.v; }
	friend bool operator != (const modnum& a, const modnum& b) { return a.v != b.v; }

	modnum inv() const {
		modnum res;
		res.v = minv(v, MOD);
		return res;
	}
	friend modnum inv(const modnum& m) { return m.inv(); }
	modnum neg() const {
		modnum res;
		res.v = v ? MOD-v : 0;
		return res;
	}
	friend modnum neg(const modnum& m) { return m.neg(); }

	modnum operator- () const {
		return neg();
	}
	modnum operator+ () const {
		return modnum(*this);
	}

	modnum& operator ++ () {
		v ++;
		if (v == MOD) v = 0;
		return *this;
	}
	modnum& operator -- () {
		if (v == 0) v = MOD;
		v --;
		return *this;
	}
	modnum& operator += (const modnum& o) {
		v += o.v;
		if (v >= MOD) v -= MOD;
		return *this;
	}
	modnum& operator -= (const modnum& o) {
		v -= o.v;
		if (v < 0) v += MOD;
		return *this;
	}
	modnum& operator *= (const modnum& o) {
		v = int(ll(v) * ll(o.v) % MOD);
		return *this;
	}
	modnum& operator /= (const modnum& o) {
		return *this *= o.inv();
	}

	friend modnum operator ++ (modnum& a, int) { modnum r = a; ++a; return r; }
	friend modnum operator -- (modnum& a, int) { modnum r = a; --a; return r; }
	friend modnum operator + (const modnum& a, const modnum& b) { return modnum(a) += b; }
	friend modnum operator - (const modnum& a, const modnum& b) { return modnum(a) -= b; }
	friend modnum operator * (const modnum& a, const modnum& b) { return modnum(a) *= b; }
	friend modnum operator / (const modnum& a, const modnum& b) { return modnum(a) /= b; }
};

template <typename T> T pow(T a, long long b) {
	assert(b >= 0);
	T r = 1; while (b) { if (b & 1) r *= a; b >>= 1; a *= a; } return r;
}

using num = modnum<int(1e9) + 7>;

vector<num> fact, ifact;

void init(){
	int N = 110;
	fact = {1};
	for(int i = 1; i < N; i++) fact.push_back(i * fact[i-1]);
	ifact.resize(N);
	ifact.back() = 1 / fact.back();
	for(int i = N - 1; i > 0; i--) ifact[i-1] = i * ifact[i];
}

num ncr(int n, int k){
	if(k < 0 || k > n) return 0;
	return fact[n] * ifact[k] * ifact[n-k];
}
int main(){
	ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	init();
	vector<int> a(3), A(3);
	for(int& x : a) cin >> x;
	for(int& x : A) cin >> x;
	for(int i = 0; i < 3; i++){
		if(A[i] % a[i] != 0){
			cout << 0 << '\n';
			return 0;
		}
		A[i] /= a[i];
	}
	num perfect = a[0] * a[1] * a[2];
	num p0 = a[1] * a[2] * pow(num(a[0]), A[1] * A[2]) - perfect;
	num p1 = a[0] * a[2] * pow(num(a[1]), A[0] * A[2]) - perfect;
	num p2 = a[0] * a[1] * pow(num(a[2]), A[0] * A[1]) - perfect;
	num p01 = a[2] * pow(a[0] * pow(num(a[1]), A[0]) + a[1] * pow(num(a[0]), A[1])
		- a[0] * a[1], A[2]) - p0 - p1 - perfect;
	num p02 = a[1] * pow(a[0] * pow(num(a[2]), A[0]) + a[2] * pow(num(a[0]), A[2])
		- a[0] * a[2], A[1]) - p0 - p2 - perfect;
	num p12 = a[0] * pow(a[1] * pow(num(a[2]), A[1]) + a[2] * pow(num(a[1]), A[2])
		- a[1] * a[2], A[0]) - p1 - p2 - perfect;


	num p012 = 0;
	for(int pull01 = 1; pull01 < A[1]; pull01++){
		for(int pull02 = 1; pull02 < A[2]; pull02++){
			num base_ways = a[0] * a[1] * a[2] * ncr(A[1], pull01) * ncr(A[2], pull02);
			num up_ways = 0;
			for(int i = 0; i <= pull01; i++){
				for(int j = 0; j <= pull02; j++){
					up_ways += pow(num(a[0]), (pull01 - i) * (pull02 - j)) * ncr(pull01, i) * ncr(pull02, j) * (((i + j) & 1) ? -1 : 1);
				}
			}
			// do some dp here?
			num no_change = 1;
			num layer1 = pow(num(a[2]), A[1] - pull01) - no_change;
			num layer2 = pow(num(a[1]), A[2] - pull02) - no_change;
			num layer_ways = pow(no_change + layer1 + layer2, A[0]) - pow(no_change + layer1, A[0]) - pow(no_change + layer2, A[0]) + pow(no_change, A[0]);
			p012 += base_ways * up_ways * layer_ways;
		}
	}
	num ans = perfect + p0 + p1 + p2 + p01 + p02 + p12 + p012;

	cout << ans << '\n';
}