Problem:
Problem F:
Chemist's Math
You have probably learnt chemical equations (chemical reaction formulae) in your high-school
days. The following are some well-known equations.
2H
2
+ O
2
→ 2H
2
O                                              (1)
                                         C
a
(OH)
2
+ CO
2
→ C
a
CO
3
+ H
2
O                      (2)
                                         N
2
+ 3H
2
→ 2NH
3
(3)
While Equations (1)–(3) all have balanced left-hand sides and right-hand sides, the following
ones do not.
Al + O
2
→ Al
2
O
3
(
wrong
)                                (4)
                                         C
3
H
8
+ O
2
→ CO
2
+ H
2
O (
wrong
)                     (5)
The equations must follow
the law of conservation of mass
; the quantity of each chemical element
(such as H, O, Ca, Al) should not change with chemical reactions. So we should "adjust" the
numbers of molecules on the left-hand side and right-hand side:
4Al + 3O
2
→ 2Al
2
O
3
(
correct
)                          (6)
                                        C
3
H
8
+ 5O
2
→ 3CO
2
+ 4H
2
O (correct)               (7)
The coefficients of Equation (6) are (4, 3, 2) from left to right, and those of Equation (7) are
(1, 5, 3, 4) from left to right. Note that the coefficient 1 may be omitted from chemical equations.
The coefficients of a
correct
equation must satisfy the following conditions.
The coefficients are all positive integers.
The coefficients are relatively prime, that is, their greatest common divisor (g.c.d.) is 1.
The quantities of each chemical element on the left-hand side and the right-hand side are
   equal.
Conversely, if a chemical equation satisfies the above three conditions, we regard it as a correct
equation, no matter whether the reaction or its constituent molecules can be chemically realized
in the real world, and no matter whether it can be called a reaction (e.g., H
2
→ H
2
is considered
correct). A chemical equation satisfying Conditions 1 and 3 (but not necessarily Condition 2)
is called a
balanced
equation.
Your goal is to read in chemical equations with missing coefficients like Equation (4) and (5),
line by line, and output the sequences of coefficients that make the equations correct.
Note that the above three conditions do not guarantee that a correct equation is uniquely
determined. For example, if we "mix" the reactions generating H
2
O and NH
3
, we would get
x
H
2
+
y
O
2
+
z
N
2
+
u
H
2
→
v
H
2
O +
w
NH
3
(8)
but (
x
,
y
,
z
,
u
,
v
,
w
) = (2, 1, 1, 3, 2, 2) does not represent a unique correct equation; for instance,
(4, 2, 1, 3, 4, 2) and (4, 2, 3, 9, 4, 6) are also "correct" according to the above definition! However,
we guarantee that every chemical equation we give you will lead to a
unique
correct equation by
adjusting their coefficients. In other words, we guarantee that (i) every chemical equation can be
balanced with positive coefficients, and that (ii)
all
balanced equations of the original equation
can be obtained by multiplying the co
...(truncated)

Submitted solutions:

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
#include <algorithm>
#include <functional>
#include <map>
#include <cctype>
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 string::const_iterator State;
typedef map<string,int> msi;
typedef vector<int> vi;
typedef vector<vi> mat;
typedef pair<string,int> P;
typedef pair<int,int> Pa;

const int MAX_eq=26*27;
msi tonum;
mat a;
int ct;
Pa memo[MAX_eq];
bool visited[MAX_eq]={};
int cnt;

bool isC(char c){
	return'A'<=c && c<='Z';
}
bool isS(char c){
	return'a'<=c && c<='z';
}
void mul(msi& m,int x){
	for(auto& v : m){
		v.sc*=x;
	}
}
void add(msi& x,msi y){
	for(auto& v : y){
		x[v.fs]+=v.sc;
	}
}
msi atom(State &be){
	//cout << "atmo";
	msi ret;
	string a;
	a+=(*be);
	be++;
	if(isS(*be)) a+=(*be),be++;
	ret[a]++;
	return ret;
}
int num(State &be){
	//cout << "num";
	int ret=0;
	while(isdigit(*be)){
		ret*=10;
		ret+=(*be)-'0';
		be++;
	}
	return ret;
}
msi mol(State &be){
	msi ret;
	while(isC(*be) || (*be)=='('){
		//cout << *be;
		msi x;
		if(isC(*be)){
			x=atom(be);
			if(isdigit(*be)) mul(x,num(be));
		}else if(*be=='('){
			be++;
			x=mol(be);
			be++;
			if(isdigit(*be)) mul(x,num(be));
		}
		add(ret,x);
	}
	return ret;
}
void seqmol(State &be){
	while(*be=='+'){
		be++;
		msi ret=mol(be);
		//for(auto v : ret) cout << tonum[v.fs] << " " << ct<<endl;
		for(auto v : ret) a[tonum[v.fs]][ct]=v.sc;
		ct++;
	}
	be++;
	while(*be!='.'){
		be++;
		msi ret=mol(be);
		mul(ret,-1);
		//for(auto v : ret) cout << tonum[v.fs] << " " << ct<<endl;
		for(auto v : ret) a[tonum[v.fs]][ct]=v.sc;
		ct++;
	}
}
int gcd(int x,int y){
	if(x<0) x=-x;
	if(y<0) y=-y;
	if(y==0) return x;
	return gcd(y,x%y);
}
int lcm(int x,int y){
	return x/gcd(x,y)*y;
}
void sweep(int eq, int var, mat& a){
	int ans=0;
	bool used[MAX_eq]={};
	rep(j,var){
		int i=0;
		while( (i < eq) && (used[i] || (a[i][j] == 0) ) ) i++;
		if(i == eq) continue;
		ans++;
		used[i] = true;
		rep(k,eq){
			if(i==k || a[k][j]==0) continue;
			int g=gcd(a[k][j],a[i][j]),akj=a[k][j];
			rep(l,var){
				a[k][l] = a[k][l]*(a[i][j]/g) - a[i][l]*(akj/g);
			}
		}
	}
}
void dfs(int id,int bunshi,int bunbo){
	memo[id]=Pa(bunshi,bunbo);
//	cout << "id"<<id<< " "<<bunshi<<"/"<<bunbo<<endl;
	visited[id]=true;
	rep(i,cnt){
		if(a[i][id]!=-0){
			rep(j,ct){
				if(j!=id&&a[i][j]!=0&&!visited[j]){
					int nshi=bunshi*a[i][id],nbo=bunbo*a[i][j];
					if(nshi<0) nshi*=-1;
					if(nbo<0) nbo*=-1;
					int g=gcd(nshi,nbo);
					nshi/=g,nbo/=g;
					dfs(j,nshi,nbo);
				}
			}
		}
	}
}
int main(){
	cnt=0;
	rep(i,26){
		string st(1,'A'+i);
		tonum.insert(P(st,cnt++));
	}
	rep(i,26) rep(j,26){
		string st(1,'A'+i);
		st+=('a'+j);
		tonum.insert(P(st,cnt++));
	}
	while(true){
		string s;
		cin>>s;
		if(s[0]=='.') break;
		s="+"+s;
		State be=s.begin();
		ct=0;
		a.clear();
		rep(i,cnt) a.pb(vi(MAX_eq,0));
		seqmol(be);
		sweep(cnt,ct,a);
		rep(i,MAX_eq) visited[i]=false;
		dfs(0,1,1);
		int lc=1;
		rep(i,ct){
			lc=lcm(lc,memo[i].sc);
		}
		rep(i,ct){
			printf("%d",memo[i].fs*lc/memo[i].sc);
			printf((i!=ct-1 ? " " : "\n"));
		}
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3112
final_rank: 2

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
#include <iomanip>
#include <fstream>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<b?(a=b,1):0)
#define chmin(a,b) (a>b?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
const double EPS = 1e-8;
typedef long long ll;
typedef pair<int,int> pii;


typedef vector<double> vec;
typedef vector<vec> mat;

ostream &operator<<(ostream &os, const vec &a) {
  FOR(it, a) {
    double a = *it;
    if (abs(*it) < EPS*EPS) a = 0;
    os << setw(3) << a << " ";
  }
  return os;
}
ostream &operator<<(ostream &os, const mat &a) {
  FOR(it, a) os << *it << endl;
  return os;
}

bool GaussElimination(const mat &A, const vec &b, vec &res) {
  int n = A.size();
  mat B(n, vec(n+1));
  REP(i,n) REP(j,n)
    B[i][j] = A[i][j];
  REP(i, n) B[i][n] = b[i];
  
  int nowy = 0;
  REP(x, n) {
    int pivot = -1;
    for (int j=nowy; j<n; ++j)
      if (pivot == -1 || abs(B[pivot][x]) < abs(B[j][x])) {
        pivot = j;
      }
    if (pivot == -1 || abs(B[pivot][x])<EPS) continue;
    swap(B[nowy], B[pivot]);

    for (int j=nowy+1; j<n; ++j) {
      double t = B[j][x] / B[nowy][x];
      for (int k=x; k<=n; ++k)
        B[j][k] = B[j][k] - B[nowy][k] * t;
    }
    nowy++;
  }
  res.clear();
  for (int y=nowy; y<n; ++y)
    if (abs(B[y][n])>EPS)                // rank(A) != rank(A|b)
      return 0;
  if (nowy != n) {              // rank(A) == rank(A|b) != n
    res = vec(n,1e100);
    for (int y=n-1; y>=0; --y) {
      int x;
      for (x=y; x<n; ++x) {
        if (abs(B[y][x])>EPS) break;
      }
      if (x==n) continue;
      double sum = B[y][n];
      for (int i=x+1; i<n; ++i) {
        if (res[i] == 1e100) res[i] = 0;
        sum -= res[i] * B[y][i];
      }
      res[x] = sum / B[y][x];
    }
    REP(i,n) if(res[i]==INF) res[i] = 0;
    return 0;
  }
  // ティツァツ」テ」ツ?古、ツクツ?ヲツ?湘」ツ?ォテヲツアツコテ」ツ?セテ」ツつ凝」ツ?づヲツ卍ョテゥツ?堙」ツ?ォテ・ツセツ古ゥツ??、ツサツ」テ・ツ?・
  res.resize(n);
  for (int x=n-1; x>=0; --x) {
    double sum = B[x][n];
    for (int i=n-1; i>x; --i) {
      sum -= res[i] * B[x][i]; 
    }
    res[x] = sum / B[x][x];
  }
  return 1;
}


vector<string> split(string s, char c) {
	vector<string> ret;
  replace(ALL(s),c,' ');
  stringstream ss(s);
  string t;
  while(ss>>t) ret.push_back(t);
  return ret;
}

int find(const string &s, char c) {
  return s.find(c);
}

typedef map<string, int> MP;
char str[100];

MP group(int &id);
MP unit_group(int &id);
int number(int &id);

MP molecule(int &id) {
  MP res;
  while(isupper(str[id])||str[id]=='(') {
    MP tmp = group(id);
    FOR(it, tmp) res[it->first] += it->second;
  }
  return res;
}

MP group(int &id) {
  MP res = unit_group(id);
  if (isdigit(str[id])) {
    int a = number(id);
    MP tmp;
    FOR(it, res) {
      tmp[it->first] = it->second*a;
    }
    res = tmp;
  }
  return res;
}
MP unit_group(int &id) {
  MP res;
  if (str[id] == '(') {
    id++;
    res = molecule(id);
    assert(str[id++] == ')');
  } else {
    assert(isupper(str[id]));
    int len = 1;
    if (islower(str[id+1])) len = 2;
    string tmp(len,' '); REP(i,len) tmp[i]=str[id+i];
    res[tmp] = 1;
    id+=len;
  }
  return res;
}

int number(int &id) {
  int res = 0;
  while(isdigit(str[id])) {
    res *= 10;
    res += str[id]-'0';
    id++;
  }
  return res;
}

bool integer(double x) {
  return abs(x-round(x)) < EPS;
}

int a[500][500];

int main() {
  string s;
  while(cin >> s, s!=".") {
    s = s.substr(0,s.size()-1);
    int pos = find(s,'-');
    string s1 = s.substr(0,pos);
    string s2 = s.substr(pos+2);
    vector<string> v1 = split(s1,'+');
    vector<string> v2 = split(s2,'+');
    memset(a,0,sizeof(a));
    int kind = 0;
    map<string,int> mp;
    REP(i,v1.size()) {
      int id = 0;
      strcpy(str, v1[i].c_str());
      MP tmp = molecule(id);
      FOR(jt, tmp) {
        string s = jt->first;
        int num = jt->second;
        // cout << "A " << s << " " << num << endl;
        if (mp.count(s)==0) {
          mp[s] = kind++;
        }
        a[mp[s]][i] = num;
      }
    }
    REP(i,v2.size()) {
      int id = 0;
      strcpy(str, v2[i].c_str());
      MP tmp = molecule(id);
      FOR(jt, tmp) {
        string s = jt->first;
        int num = jt->second;
        // cout << "B " << s << " " << num << endl;
        if (mp.count(s)==0) {
          mp[s] = kind++;
        }
        a[mp[s]][v1.size()+i] = -num;
      }      
    }
    a[kind++][0] = 1;
    int N = v1.size()+v2.size();
    mat A(kind,vec(kind));
    vec b(kind);
    REP(i,kind)REP(j,N) A[i][j]=a[i][j];
    // cout << A << endl; cout << endl;
    b[kind-1] = 1;
    vec x;
    GaussElimination(A,b,x);
    // cout << "A" << endl;
    // cout << A.size() << " " << A[0].size() << endl;
    // cout << b.size() << endl;
    // cout << x << endl;
    for (int i=1; i<=40000; ++i) {
      vec t(x);
      bool ok = 1;
      FOR(it, t) if (!integer(*it *= i)) {
        ok = 0;
        break;
      }
      if (ok) {
        REP(i,N) {
          if (i) cout << " ";
          cout << t[i];
        }
        cout << endl;
        break;
      }
    }
  }
}
accuracy: 1
time_ms: 10
memory_kb: 2336
final_rank: 1

code_snippet: #include<map>
#include<cctype>
#include<cstdio>
#include<string>
#include<vector>
#include<cassert>

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

using namespace std;

typedef long long ll;

ll gcd(ll a,ll b){ return b?gcd(b,a%b):a; }
ll lcm(ll a,ll b){ return a/gcd(a,b)*b; }

/*** RATIONAL LIBRARY BEGIN ***/
template<class T>
class rational{
	T nu,de;
	void reg(){ if(de<0) nu*=-1, de*=-1; }

public:
	// constructor
	rational():nu(0),de(1){}
	rational(const T &v):nu(v),de(1){}
	rational(const T &n,const T &d):nu(n),de(d){
		T g=gcd(nu,de);
		nu/=g;
		de/=g;
		reg();
	}

	// getter
	const T &n(){ return nu; }
	const T &d(){ return de; }

	// 算術演算
	rational &operator+=(const rational &r){
		T g=gcd(de,r.de);
		de/=g;
		nu=nu*(r.de/g)+r.nu*de;
		g=gcd(nu,g);
		nu/=g;
		de*=r.de/g;
		reg();
		return *this;
	}

	rational &operator-=(const rational &r){
		T g=gcd(de,r.de);
		de/=g;
		nu=nu*(r.de/g)-r.nu*de;
		g=gcd(nu,g);
		nu/=g;
		de*=r.de/g;
		reg();
		return *this;
	}

	rational &operator*=(const rational &r){
		T g1=gcd(nu,r.de),g2=gcd(de,r.nu);
		nu=(nu/g1)*(r.nu/g2);
		de=(de/g2)*(r.de/g1);
		reg();
		return *this;
	}

	rational &operator/=(const rational &r){
		T g1=gcd(nu,r.nu),g2=gcd(de,r.de);
		nu=(nu/g1)*(r.de/g2);
		de=(de/g2)*(r.nu/g1);
		reg();
		return *this;
	}

	rational operator+(const rational &r)const{ return rational(*this)+=r; }
	rational operator-(const rational &r)const{ return rational(*this)-=r; }
	rational operator*(const rational &r)const{ return rational(*this)*=r; }
	rational operator/(const rational &r)const{ return rational(*this)/=r; }

	rational operator-()const{ return rational<T>(-nu,de); }

	// 比較演算
	bool operator<(const rational &r)const{ return nu*r.de<r.nu*de; } // overflow 注意
	bool operator>(const rational &r)const{ return r<*this; }
	bool operator<=(const rational &r)const{ return !(r<*this); }
	bool operator>=(const rational &r)const{ return !(*this<r); }
	bool operator==(const rational &r)const{ return nu==r.nu && de==r.de; }
	bool operator!=(const rational &r)const{ return !(*this==r); }
};
/*** RATIONAL LIBRARY END ***/

rational<ll> abs(const rational<ll> &r){ return r>=0?r:-r; }

void operator+=(vector<ll> &a,const vector<ll> &b){ rep(i,80) a[i]+=b[i]; }

int row;
ll A[80][80]; // 係数行列

map<string,int> f; // 原子の名前 -> id

int idx;
char s[128];

vector<ll> molecule();

int number(){
	int num=0;
	while(isdigit(s[idx])) num=num*10+(s[idx++]-'0');
	return num;
}

vector<ll> chemical_element(){
	string name;
	name+=s[idx++];
	if(islower(s[idx])) name+=s[idx++];

	int id;
	if(f.count(name)!=0) id=f[name];
	else{
		id=f.size();
		f[name]=id;
	}

	vector<ll> a(80);
	a[id]=1;
	return a;
}

vector<ll> unit_group(){
	if(s[idx]!='('){
		return chemical_element();
	}
	else{
		idx++;
		vector<ll> a=molecule();
		assert(s[idx++]==')');
		return a;
	}
}

vector<ll> group(){
	vector<ll> a=unit_group();
	if(isdigit(s[idx])){
		int num=number();
		rep(i,80) a[i]*=num;
	}
	return a;
}

vector<ll> molecule(){
	vector<ll> a=group();
	while(isupper(s[idx]) || s[idx]=='(') a+=group();
	return a;
}

void molecule_sequence(int sign){
	vector<ll> a=molecule();
	rep(i,80) A[row][i]+=sign*a[i];
	for(row++;s[idx]=='+';row++){
		idx++;
		a=molecule();
		rep(i,80) A[row][i]+=sign*a[i];
	}
}

void chemical_equation(){
	molecule_sequence(+1);
	assert(s[idx++]=='-');
	assert(s[idx++]=='>');
	molecule_sequence(-1);
	assert(s[idx++]=='.');
}

void parse(){
	f.clear();
	rep(i,80) rep(j,80) A[i][j]=0;
	idx=row=0;
	chemical_equation();
}

const int N_MAX=80;
void Gauss_Jordan(int n,const rational<ll> A[N_MAX][N_MAX],const rational<ll> *b,rational<ll> *x){
	static rational<ll> 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(B[i][i]==0) break;

		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];
}

int main(){
	for(;fgets(s,128,stdin),s[0]!='.';){
		parse();

		rational<ll> A[80][80],b[80],x[80];
		rep(i,80) rep(j,80) A[j][i]=::A[i][j];
		A[79][0]=b[79]=1; // 一つめの変数の値を 1 に固定する

		Gauss_Jordan(80,A,b,x);

		ll L=1;
		rep(i,row) L=lcm(L,x[i].d());
		rep(i,row) x[i]*=L;
		ll G=0;
		rep(i,row) G=gcd(G,x[i].n());
		rep(i,row) x[i]/=G;
		rep(i,row) printf("%lld%c",x[i].n(),i<row-1?' ':'\n');
	}

	return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 1308
final_rank: 2