Problem:
Problem F:
Numoeba
A scientist discovered a strange variation of amoeba. The scientist named it
numoeba
. A numoeba, though it looks like an amoeba, is actually a community of cells, which always forms a tree.
The scientist called the cell
leader
that is at the root position of the tree. For example, in Fig. 1, the leader is
A
. In a numoeba, its leader may change time to time. For example, if
E
gets new leadership, the tree in Fig. 1 becomes one in Fig. 2. We will use the terms root, leaf, parent, child and subtree for a numoeba as defined in the graph theory.
Numoeba changes its physical structure at every biological clock by cell division and cell death. The leader may change depending on this physical change.
The most astonishing fact about the numoeba cell is that it contains an organic unit called
numbosome
, which represents an odd integer within the range from 1 to 12,345,677. At every biological clock, the value of a numbosome changes from n to a new value as follows:
The maximum odd factor of 3
n
+ 1 is calculated. This value can be obtained from 3
n
+ 1 by repeating division by 2 while even.
If the resulting integer is greater than 12,345,678, then it is subtracted by 12,345,678.
For example, if the numbosome value of a cell is 13, 13 × 3 + 1 = 40 is divided by 2
3
= 8 and a new numbosome value 5 is obtained. If the numbosome value of a cell is 11,111,111, it changes to 4,320,989, instead of 16,666,667. If 3
n
+ 1 is a power of 2, yielding 1 as the result, it signifies the death of the cell as will be described below.
At every biological clock, the next numbosome value of every cell is calculated and the fate of the cell and thereby the fate of numoeba is determined according to the following steps.
A cell that is a leaf and increases its numbosome value is designated as a
candidate
leaf.
A cell dies if its numbosome value becomes 1. If the dying cell is the leader of the numoeba, the numoeba dies as a whole. Otherwise, all the cells in the subtree from the dying cell (including itself) die. However, there is an exceptional case where the cells in the subtree do not necessarily die; if there is only one child cell of the dying non-leader cell, the child cell will replace the dying cell. Thus, a straight chain simply shrinks if its non-leader constituent dies.
For example, consider a numoeba with the leader A below.
If the leader A dies in (1), the numoeba dies.
If the cell D dies in (1), (1) will be as follows.
And, if the cell E dies in (1), (1) will be as follows.
Note that this procedure is executed sequentially, top-down from the root of the numoeba to leaves. If the cells
E
and
F
will die in (1), the death of
F
is not detected at the time the procedure examines the cell
E
. The numoeba, therefore, becomes (3). One should not consider in such a way that the death of
F
makes
G
the only child of
E
, and, therefore,
G
will replace the dying
E
.
If a
candidate
leaf survives with the numbosome value of
n
, it spawns a cell as its child,
...(truncated)

Submitted solutions:

code_snippet: #include<iostream>
#include<vector>
#include<tuple>
#include<algorithm>
using namespace std;

const int MOD = 12345678;
const int NIL = -1;

class Numoeba {
public:
    Numoeba(const int n) :max_cell_(1), root_(0) {create_cell(n);}
    tuple<int, int> die() {
        for(int step = 1; step <= 500; ++step) {
            int t = dead_.size() - count(dead_.begin(), dead_.end(), true);
            max_cell_ = max(max_cell_, t);
            vector<int> candidate;
            int new_leader_id, new_leader_n = NIL;
// cout<<step<<endl;
// cout<<"root: "<<root_<<endl;
// cout<<"dead: ";for(const auto&d:dead_)cout<<" "<<d;cout<<endl;
// cout<<"numb: ";for(const auto&d:numbosome_)cout<<" "<<d;cout<<endl;
            if(traverse(root_, NIL, candidate, new_leader_id, new_leader_n)) return tuple<int, int>(step, max_cell_);
            for(auto& e: edge_) for(int i = 0; i < e.size(); ++i) if(dead_[e[i]]) e.erase(e.begin() + i--);
// cout<<"candidate: ";for(const auto&d:candidate)cout<<" "<<d;cout<<endl;
            for(const auto& c: candidate) {
                int n = (numbosome_[c] + 1) / 2;
                if(!(n & 1)) ++n;
//                 if(n <= 1) continue;
//                 if(dead_[c]) continue;
                add_child(c, create_cell(n));
            }
            if(new_leader_id == NIL) continue;
            root_ = new_leader_id;
            int n = (numbosome_[root_] + 1) / 2;
            if(!(n & 1)) --n;
//             if(n <= 1) continue;
            add_child(root_, create_cell(n));
        }
        return tuple<int, int>(NIL, max_cell_);
    }
private:
    bool traverse(const int current, const int previous, vector<int>& candidate, int& new_leader_id, int& new_leader_n) {
        int pn = numbosome_[current];
        if(update(current) == 1) {
            dead_[current] = true;
            if(current == root_) return true;
            if(edge_[current].size() == 2) {
                int next = edge_[current][0];
                if(next == previous) next = edge_[current][1];
                for(auto& id: edge_[previous]) if(id == current) id = next;
                for(auto& id: edge_[next]) if(id == current) id = previous;
                return traverse(next, previous, candidate, new_leader_id, new_leader_n);
            }
            for(const auto& next: edge_[current]) if(next != previous) erase(next, current);
            return false;
        }
        if(numbosome_[current] > pn && edge_[current].size() <= 1) candidate.push_back(current);
        if(numbosome_[current] == new_leader_n) new_leader_id = NIL;
        if(numbosome_[current] > new_leader_n) {
            new_leader_n = numbosome_[current];
            new_leader_id = current;
        }
        for(const auto& next: edge_[current]) {
            if(next == previous) continue;
            if(traverse(next, current, candidate, new_leader_id, new_leader_n)) return true;
        }
        return false;
    }
    void erase(const int current, const int previous) {
        dead_[current] = true;
        for(const auto& next: edge_[current]) if(next != previous) erase(next, current);
    }
    int create_cell(const int n) {
        numbosome_.push_back(n);
        dead_.push_back(false);
        edge_.push_back(vector<int>());
        return (dead_.size() - 1);
    }
    void add_child(const int pid, const int cid) {
        edge_[pid].push_back(cid);
        edge_[cid].push_back(pid);
    }
    int update(const int id) {
        numbosome_[id] = numbosome_[id] * 3 + 1;
        while(!(numbosome_[id] & 1)) numbosome_[id] >>= 1;
        if(numbosome_[id] > MOD) numbosome_[id] -= MOD;
//         while(numbosome_[id] > MOD) numbosome_[id] -= MOD;
        return numbosome_[id];
    }
    int root_;
    int max_cell_;
    vector<int> numbosome_;
    vector<bool> dead_;
    vector<vector<int>> edge_;
public:
void print(){
cout<<"root: "<<root_<<endl;
cout<<"dead: ";for(const auto&d:dead_)cout<<" "<<d;cout<<endl;
cout<<"numb: ";for(const auto&d:numbosome_)cout<<" "<<d;cout<<endl;
cout<<dead_.size()<<endl;
}
};


int main() {
    int k;
    while(cin >> k, k) {
        Numoeba n(k);
        int step, numbosome;
        tie(step, numbosome) = n.die();
        cout << step << " " << numbosome << endl;
//         n.print();
    }
}
accuracy: 1
time_ms: 10
memory_kb: 1484
final_rank: 4

code_snippet: #include<cstdio>
#include<vector>

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

using namespace std;

int idx,val[5000];
bool cand[5000]; // candidate leaf かどうか
vector<int> G[5000];

// u を根とする部分木を削除
void destroy(int u,int pre){
	rep(i,G[u].size()) if(G[u][i]!=pre) destroy(G[u][i],u);
	G[u].clear();
}

// numbosome の計算
void dfs0(int u,int pre){
	int a=3*val[u]+1;
	while(a%2==0) a/=2;
	if(a>12345678) a-=12345678;
	cand[u]=(G[u].size()<=1&&val[u]<a);
	val[u]=a;
	rep(i,G[u].size()) if(G[u][i]!=pre) dfs0(G[u][i],u);
}

// val==1 の頂点を削除
bool dfs1(int u,int pre){
	if(val[u]==1){
		if(pre!=-1 && G[u].size()==2){ // special case
			int v=(G[u][0]==pre?G[u][1]:G[u][0]);
			G[u].clear();
			rep(i,G[v].size()) if(G[v][i]==u) G[v].erase(G[v].begin()+i);
			G[pre].push_back( v );
			G[ v ].push_back(pre);
			dfs1(v,pre);
			return false;
		}
		else{
			destroy(u,pre);
			return pre==-1;
		}
	}
	else{
		rep(i,G[u].size()) if(G[u][i]!=pre) {
			int v=G[u][i];
			if(val[v]==1) G[u].erase(G[u].begin()+i--);
			dfs1(v,u);
		}
		return false;
	}
}

// leaf bonus の処理
void dfs2(int u,int pre){
	if(cand[u]){
		G[ u ].push_back(idx);
		G[idx].push_back( u );
		val[idx]=(val[u]+1)/2;
		if(val[idx]%2==0) val[idx]++;
		idx++;
	}
	else{
		rep(i,G[u].size()) if(G[u][i]!=pre) dfs2(G[u][i],u);
	}
}

// 生きている頂点のリストを求める
void dfs3(int u,int pre,vector<int> &res){
	res.push_back(u);
	rep(i,G[u].size()) if(G[u][i]!=pre) dfs3(G[u][i],u,res);
}

int main(){
	while(scanf("%d",val),val[0]){
		idx=1;
		int t,leader=0,sz=1;
		for(t=1;;t++){
			// step 0
			dfs0(leader,-1);

			// step 1
			if(dfs1(leader,-1)) break;

			// step 2
			dfs2(leader,-1);

			// step 3
			vector<int> seq;
			dfs3(leader,-1,seq);
			int next=-1;
			bool dup=false;
			rep(i,seq.size()){
				if(next==-1 || val[seq[i]]>val[next]){
					next=seq[i];
					dup=false;
				}
				else if(val[seq[i]]==val[next]){
					dup=true;
				}
			}
			if(!dup){ // leader bonus
				leader=next;
				G[leader].push_back(idx);
				G[idx].push_back(leader);
				val[idx]=(val[leader]+1)/2;
				if(val[idx]%2==0) val[idx]--;
				seq.push_back(idx);
				idx++;
			}

			sz=max(sz,(int)seq.size());
		}

		printf("%d %d\n",t,sz);
	}

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1344
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;

const int MOD = 12345678;


class Cell
{
public:
  int v;
  Cell* parent;
  bool visited, candidate,leaf;
  vector<Cell*> child;

  Cell(int v, Cell* parent)
    :v(v),parent(parent),visited(false),candidate(false),leaf(false)
  {}

  void update() {
    int p = v;
	v = 3*v + 1;

    while(v%2!=1) {
      v/=2;
    }

    v %= MOD;
	if(p < v) candidate = true;
  }
};

int count(Cell* cell)
{
	int res = 1;
	for(int i=0; i<cell->child.size(); i++)
		res += count(cell->child[i]);

	return res;
}

void getValues(Cell* cell, vector<int>& res)
{
	res.push_back(cell->v);
	for(int i=0; i<cell->child.size(); i++) {
		getValues(cell->child[i], res);
	}
}

Cell* getNewLeader(Cell* cell, int v)
{
	if(cell->v == v) return cell;

	for(int i=0; i<cell->child.size(); i++){
		Cell* res = getNewLeader(cell->child[i], v);
		if(res != NULL) return res;
	}

	return NULL;
}

void checkLeaf(Cell* cell)
{
	if(cell->child.size() == 0) cell->leaf = true;
	for(int i=0; i<cell->child.size(); i++) {
		checkLeaf(cell->child[i]);
	}
}

Cell* selectLeader(Cell* root, bool& uniq)
{
	vector<int> values;
	getValues(root, values);

	sort(values.begin(), values.end(), greater<int>());

	if(values[0] == values[1]) {
		uniq = false;
		return root->child[0];
	}

	uniq = true;
	Cell* newleader = getNewLeader(root, values[0]);

	return newleader;
}

void add(Cell* parent, int v)
{
	parent->child.push_back(new Cell(v, parent));
}

void leaderBonus(Cell* leader)
{
  int v = (leader->v+1)/2;
  if(v%2==0) v -= 1;

  add(leader, v);
}

void leafBonus(Cell* cell)
{
	if(cell->leaf){
      int v = (cell->v+1)/2;
      if(v%2==0) v += 1;

      if(cell->candidate) {
		 add(cell, v);
	  }
    }
	else{
      for(int i=0; i<cell->child.size(); i++)
		leafBonus(cell->child[i]);
    }
}

void newTree(Cell* prev, Cell* next)
{
  prev->visited = true;
  Cell* c = new Cell(prev->v, next);
  next->child.push_back(c);

  if(prev->parent) {
    if(!prev->parent->visited) {
      if(prev->parent->v != -1) {
		prev->parent->visited = true;
		newTree(prev->parent, c);
      }
    }
  
    for(int i=0; i<prev->child.size(); i++) {
      if(!prev->child[i]->visited) {
		prev->child[i]->visited = true;
		newTree(prev->child[i], c);
      }
    }
  }
}

void remove(Cell *cell)
{
	for(int i=0; i<cell->child.size(); i++) {
		remove(cell->child[i]);
	}

	delete cell;
}

bool died(Cell *cell, bool leader)
{
	if(cell->v == 1) {
		if(leader) {
			remove(cell);
		}
		else {
			Cell* parent = cell->parent;
			int n=-1;
			for(int i=0; i<parent->child.size(); i++) {
				if(parent->child[i] == cell) 
					n = i;
			}

			parent->child.erase(parent->child.begin()+n);
			
			if(cell->child.size() != 1)
			{
				remove(cell);
			}
			else {
				Cell* grandchild = cell->child[0];

				parent->child.push_back(grandchild);
				grandchild->parent = parent;
		
				delete cell;
				cell = NULL;
			}

			died(parent, false);
			return true;
		}
	}
	else {
		for(int i=0; i<cell->child.size(); i++) 
			if(died(cell->child[i], false)) break;
	}
	

  return false;
}

void update(Cell* cell)
{
	cell->update();
	for(int i = 0; i < cell->child.size(); i++) {
		update(cell->child[i]);
	}
}

void solve(int v)
{
  Cell* root = new Cell(-1, NULL);
  root->visited = true;
  add(root, v);

  Cell* leader = root->child[0];
  
  int cycle = 0, m = 1;
  while(1) {
    cycle++;

    update(leader);
	checkLeaf(leader);

	died(root, true);
	if(root->child.size() == 0) break;

	leafBonus(leader);

    Cell* newroot = new Cell(-1, NULL);
	newroot->visited = true;

	bool uniq;
    leader = selectLeader(root, uniq);
    newTree(leader, newroot);

	leader = newroot->child[0]; 

    if(uniq) leaderBonus(leader);

    m = max(m, count(leader));

    remove(root->child[0]);

    root = newroot;
  }

  cout << cycle << " " << m << endl;
}

int main()
{
  int N;
  while(cin >> N, N)
  {
      solve(N);
  }
}
accuracy: 1
time_ms: 90
memory_kb: 1008
final_rank: 8

code_snippet: #include<cstdio>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
using namespace std;
typedef set<int> Edge;
struct Cell
{
	int v;
	Edge edge;
	Cell(int v):v(v),edge(){}
	Cell():v(-1),edge(){}
};
typedef map<int,Cell>Numoeba;
typedef Numoeba::value_type Pair;

Numoeba numoeba;
int makeIndex;

int Collatz(int x)
{
	x=3*x+1;
	while(x%2==0)
		x/=2;
	if(x>=12345678)
		x-=12345678;
	return x;
}
void ConnectEdge(int x,int y)
{
	numoeba.find(x)->second.edge.insert(y);
	numoeba.find(y)->second.edge.insert(x);
}
void EraseEdge(int controlIndex,int erasedIndex)
{
	numoeba.find(controlIndex)->second.edge.erase(erasedIndex);
}
void Spawn(int K,int fromID)
{
	numoeba.insert( Pair(makeIndex,Cell(K)) );
	ConnectEdge(fromID, makeIndex);
	++makeIndex;
}
void Kill(int id,int fromID,bool willDie)
{
	const Cell &cell=numoeba.find(id)->second;
	if(cell.v==1 || willDie)
	{
		if(!willDie && fromID>=0 && cell.edge.size()==2)
		{
			Edge::iterator ite=cell.edge.begin();
			if(*ite==fromID)
				++ite;
			int childID = *ite;
			EraseEdge(fromID, id);
			EraseEdge(childID,id);
			ConnectEdge(childID,fromID);
			numoeba.erase(id);
			Kill(childID,fromID,false);
		}
		else
		{
			for(Edge::iterator ite=cell.edge.begin(); ite!=cell.edge.end();)
			{
				if(*ite!=fromID)
					Kill(*(ite++), id, true);
				else ++ite;
			}
			if(fromID>=0)
				EraseEdge(fromID,id);
			numoeba.erase(id);
		}
	}
	else
	{
		for(Edge::iterator ite=cell.edge.begin(); ite!=cell.edge.end();)
			if(*ite!=fromID)
				Kill(*(ite++),id,false);
			else ++ite;
	}
}

int main()
{
	vector<int>candidate;
	int K,T,maxCell,rootIndex, i;
	while(scanf("%d",&K),K)
	{
		maxCell=1;
		rootIndex = makeIndex = 0;
		numoeba.clear();
		numoeba.insert(Pair(makeIndex++,Cell(K)));
		for(T=1;;++T)
		{
			candidate.clear();
			for(Numoeba::iterator ite=numoeba.begin(); ite!=numoeba.end(); ++ite)
			{
				int x=Collatz(ite->second.v);
				if(x>ite->second.v && (ite->second.edge.size()==1&&ite->first!=rootIndex || numoeba.size()==1))
					candidate.push_back(ite->first);
				ite->second.v = x;
			}
			Kill(rootIndex,-1,false);
			if(numoeba.empty())
				break;

			for(i=0; i<candidate.size(); ++i)
			{
				Numoeba::iterator ite=numoeba.find(candidate[i]);
				if(ite!=numoeba.end())
				{
					int v=(ite->second.v+1)/2;
					if(v%2==0)++v;
					Spawn(v,candidate[i]);
				}
			}
			int maxV=0, count=0, index=-1;
			for(Numoeba::iterator ite=numoeba.begin(); ite!=numoeba.end(); ++ite)
			{
				int v=ite->second.v;
				if(maxV < v)
				{
					maxV = v;
					index=ite->first;
					count=1;
				}
				else if(maxV == v)
					++count;
			}
			if(count==1)
			{
				int v=(maxV+1)/2;
				if(v%2==0)--v;
				Spawn(v,index);
				rootIndex = index;
			}
			maxCell = max<int>(maxCell, numoeba.size());
		}
		printf("%d %d\n",T,maxCell);
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 868
final_rank: 3

code_snippet: #include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

class Cell
{
public:
    int value;
    list<Cell*> to;
    bool candidate;

    Cell(int value0){
        value = value0;
    }
    ~Cell(){
        list<Cell*>::iterator it = to.begin();
        while(it != to.end()){
            (*it)->to.erase(find((*it)->to.begin(), (*it)->to.end(), this));
            delete *it;
            ++ it;
        }
    }

    void updateValue()
    {
        long long a = value;
        a *= 3;
        ++ a;
        while(a % 2 == 0)
            a /= 2;
        -- a;
        a %= 12345678;
        ++ a;
        candidate = (a > value);
        value = a;
    }

    void update(Cell* prev)
    {
        updateValue();
        candidate &= (to.size() == 0 || (prev != NULL && to.size() == 1));

        if(value == 1){
            if(prev != NULL && to.size() == 2){
                list<Cell*>::iterator it = to.begin();
                if(*it == prev)
                    ++ it;
                prev->to.push_back(*it);
                *find((*it)->to.begin(), (*it)->to.end(), this) = prev;
                to.erase(it);
            }
            return;
        }

        list<Cell*>::iterator it = to.begin();
        while(it != to.end()){
            if(*it != prev){
                (*it)->update(this);
                if((*it)->value == 1){
                    (*it)->to.erase(find((*it)->to.begin(), (*it)->to.end(), this));
                    delete *it;
                    it = to.erase(it);
                }else{
                    ++ it;
                }
            }else{
                ++ it;
            }
        }

        if(candidate){
            int a = (value + 1) / 2;
            if(a % 2 == 0)
                ++ a;
            Cell* c = new Cell(a);
            c->to.push_back(this);
            to.push_back(c);
        }
    }

    static Cell* maxCell;
    static int maxValue;
    static bool ng;
    int findMax(Cell* prev)
    {
        if(value > maxValue){
            maxValue = value;
            maxCell = this;
            ng = false;
        }else if(value == maxValue){
            ng = true;
        }

        int num = 1;
        list<Cell*>::iterator it = to.begin();
        while(it != to.end()){
            if(*it != prev){
                num += (*it)->findMax(this);
            }
            ++ it;
        }

        return num;
    }

    void addLeaderBonus()
    {
        int a = (value + 1) / 2;
        if(a % 2 == 0)
            -- a;
        Cell* c = new Cell(a);
        c->to.push_back(this);
        to.push_back(c);
    }
};
Cell* Cell::maxCell;
int Cell::maxValue;
bool Cell::ng;

Cell* leader;

int main()
{
    for(;;){
        int n;
        cin >> n;
        if(n == 0)
            return 0;

        leader = new Cell(n);
        int t = 0;
        int ret = 1;
        for(;;){
            ++ t;
            leader->update(NULL);
            if(leader->value == 1)
                break;

            Cell::maxValue = -1;
            int num = leader->findMax(NULL);
            if(!Cell::ng){
                leader = Cell::maxCell;
                leader->addLeaderBonus();
                ++ num;
            }
            ret = max(ret, num);
        }

        cout << t << ' ' << ret << endl;

        delete leader;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1

code_snippet: #include<cstdlib>
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()
#define pb         push_back

class Tree{
public:
  int value;
  vector<Tree*> child;
  Tree *parent;
  bool iscand;
  Tree(){};
  Tree(int tv,Tree *tp){
    child.clear();
    parent=tp;
    value=tv;
    iscand=false;
    child.pb(tp);
  }
  bool isvalid(int i){
    if (child[i] == NULL || child[i] == parent)return false;
    return true;
  }
  void del(Tree *now){
    rep(i,child.size()){
      if (now == child[i]){
	child.erase(child.begin()+i);
	i--;
      }
    }
  }
  int count_valid(){
    int cnt=0;
    rep(i,child.size()){
      if (isvalid(i))cnt++;
    }
    return cnt;
  }
};

int compute(int n){
  n = 3*n+1;
  while(n%2 == 0)n/=2;
  if (n > 12345678)n-=12345678;
  return n;
}

void update(Tree *now){
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    update(now->child[i]);
  }
  int tmp=now->value;
  now->value=compute(now->value);
  if (now->count_valid() ==0 && tmp < now->value)now->iscand=true;
  else now->iscand=false;
}


void get_all_death(Tree *now,vector<Tree*> &wildel){
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    get_all_death(now->child[i],wildel);
  }
  wildel.pb(now);
}

bool death(Tree *now,vector<Tree*> &wildel){
  if (now->value == 1){
    int cnt = 0;//count child
    Tree *ins=NULL;
    rep(i,now->child.size()){
      if (now->isvalid(i)){
	cnt++;
	ins=now->child[i];
      }
    }
    if (cnt == 1 && now->parent != NULL){
      now->parent->child.pb(ins);//because of chain
      ins->parent=now->parent;
      ins->del(now);
      ins->child.pb(now->parent);

      wildel.pb(now);
    }else get_all_death(now,wildel);
    return true;
  }

  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    if (death(now->child[i],wildel)){
      now->child.erase(now->child.begin()+i);
      i--;
    }
  }
  return false;//survive
}

void make_child(Tree *now){
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    make_child(now->child[i]);
  }
  
  if (now->iscand){
    int newvalue = (now->value+1)/2;
    if (newvalue%2 == 0)newvalue++;
    Tree *newnode;
    newnode = new Tree(newvalue,now);
    now->child.pb(newnode);
  }
}

void find_new_leader(Tree *now,int &maxval,int &maxcnt,Tree* &who){
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    find_new_leader(now->child[i],maxval,maxcnt,who);
  }
  
  if (now->value > maxval){
    maxval=now->value;
    maxcnt=1;
    who=now;
  }else if (now->value == maxval)maxcnt++;
}

void replace(Tree *now,Tree *parent){
  if (now == NULL)return;
  replace(now->parent,now);
  now->parent=parent;
}

Tree* find_leader(Tree *root){
  int maxval=0,maxcnt=0;
  Tree *who=NULL;
  find_new_leader(root,maxval,maxcnt,who);
  if (maxcnt == 1){
    replace(who,NULL);
    int newvalue = (who->value+1)/2;
    if (newvalue %2 == 0)newvalue--;

    Tree *bonus;
    bonus=new Tree(newvalue,who);
    who->child.pb(bonus);
    return who;
  }else return root;
}

void del_travarse(Tree *now,vector<Tree*> &wildel){
  rep(i,now->child.size()){
   if (!now->isvalid(i))continue;
   del_travarse(now->child[i],wildel);
  }

  rep(i,wildel.size()){
    now->del(wildel[i]);
  }
}

bool operation_death(Tree *root){
  bool ret=false;
  vector<Tree*> wildel;
  if (death(root,wildel))ret=true;
  del_travarse(root,wildel);
  rep(i,wildel.size())free(wildel[i]);
  return ret;
}

void count_node(Tree *now,int &cnt){
  cnt++;
  rep(i,now->child.size()){
   if (!now->isvalid(i))continue;
   count_node(now->child[i],cnt);
  }
}

void solve(int val){
  Tree *root;
  root=new Tree(val,NULL);
  int cnt=1;
  int maxnum=1;
  while(true){
    update(root);
    if (operation_death(root))break;
    make_child(root);
    root = find_leader(root);
    int tmp = 0;
    count_node(root,tmp);
    maxnum=max(maxnum,tmp);
    cnt++;
  }
  
  cout << cnt <<" " << maxnum << endl;
  return;
}

main(){
  int n;
  while(cin>>n && n){
    solve(n);
  }
}
accuracy: 1
time_ms: 40
memory_kb: 0
final_rank: 2

code_snippet: #include<cstdlib>
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()
#define pb         push_back

class Tree{
public:
  int value;
  vector<Tree*> child;
  Tree *parent;
  bool iscand;
  Tree(){};
  Tree(int tv,Tree *tp){
    child.clear();
    parent=tp;
    value=tv;
    iscand=false;
    child.pb(tp);
  }
  bool isvalid(int i){
    if (child[i] == NULL || child[i] == parent)return false;
    return true;
  }
  void del(Tree *now){
    rep(i,child.size()){
      if (now == child[i]){
	child.erase(child.begin()+i);
	i--;
      }
    }
  }
  int count_valid(){
    int cnt=0;
    rep(i,child.size()){
      if (isvalid(i))cnt++;
    }
    return cnt;
  }
};

int compute(int n){
  n = 3*n+1;
  while(n%2 == 0)n/=2;
  if (n > 12345678)n-=12345678;
  return n;
}

void update(Tree *now){
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    update(now->child[i]);
  }
  int tmp=now->value;
  now->value=compute(now->value);
  if (now->count_valid() ==0 && tmp < now->value)now->iscand=true;
  else now->iscand=false;
}


void get_all_death(Tree *now,vector<Tree*> &wildel){
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    get_all_death(now->child[i],wildel);
  }
  wildel.pb(now);
}

bool death(Tree *now,vector<Tree*> &wildel){
  if (now->value == 1){
    int cnt = 0;//count child
    Tree *ins=NULL;
    rep(i,now->child.size()){
      if (now->isvalid(i)){
	cnt++;
	ins=now->child[i];
      }
    }
    if (cnt == 1 && now->parent != NULL){
      now->parent->child.pb(ins);//because of chain
      ins->parent=now->parent;
      ins->del(now);
      ins->child.pb(now->parent);

      wildel.pb(now);
    }else get_all_death(now,wildel);
    return true;
  }

  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    if (death(now->child[i],wildel)){
      now->child.erase(now->child.begin()+i);
      i--;
    }
  }
  return false;//survive
}

void make_child(Tree *now){
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    make_child(now->child[i]);
  }
  
  if (now->iscand){
    int newvalue = (now->value+1)/2;
    if (newvalue%2 == 0)newvalue++;
    Tree *newnode;
    newnode = new Tree(newvalue,now);
    now->child.pb(newnode);
  }
}

void find_new_leader(Tree *now,int &maxval,int &maxcnt,Tree* &who){
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    find_new_leader(now->child[i],maxval,maxcnt,who);
  }
  
  if (now->value > maxval){
    maxval=now->value;
    maxcnt=1;
    who=now;
  }else if (now->value == maxval)maxcnt++;
}

void replace(Tree *now,Tree *parent){
  if (now == NULL)return;
  replace(now->parent,now);
  now->parent=parent;
}

Tree* find_leader(Tree *root){
  int maxval=0,maxcnt=0;
  Tree *who=NULL;
  find_new_leader(root,maxval,maxcnt,who);
  if (maxcnt == 1){
    replace(who,NULL);
    int newvalue = (who->value+1)/2;
    if (newvalue %2 == 0)newvalue--;

    Tree *bonus;
    bonus=new Tree(newvalue,who);
    who->child.pb(bonus);
    return who;
  }else return root;
}

void del_travarse(Tree *now,vector<Tree*> &wildel){
  rep(i,now->child.size()){
   if (!now->isvalid(i))continue;
   del_travarse(now->child[i],wildel);
  }

  rep(i,wildel.size()){
    now->del(wildel[i]);
  }
}

bool operation_death(Tree *root){
  bool ret=false;
  vector<Tree*> wildel;
  if (death(root,wildel))ret=true;
  //  del_travarse(root,wildel);
  //  rep(i,wildel.size())free(wildel[i]);
  return ret;
}

void count_node(Tree *now,int &cnt){
  cnt++;
  rep(i,now->child.size()){
   if (!now->isvalid(i))continue;
   count_node(now->child[i],cnt);
  }
}

void solve(int val){
  Tree *root;
  root=new Tree(val,NULL);
  int cnt=1;
  int maxnum=1;
  while(true){
    update(root);
    if (operation_death(root))break;
    make_child(root);
    root = find_leader(root);
    int tmp = 0;
    count_node(root,tmp);
    maxnum=max(maxnum,tmp);
    cnt++;
  }
  
  cout << cnt <<" " << maxnum << endl;
  return;
}

main(){
  int n;
  while(cin>>n && n){
    solve(n);
  }
}
accuracy: 1
time_ms: 20
memory_kb: 1436
final_rank: 6

code_snippet: #include<cstdlib>
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()
#define pb         push_back

class Tree{
public:
  int value;
  vector<Tree*> child;
  Tree *parent;
  bool iscand;
  Tree(){};
  Tree(int tv,Tree *tp){
    child.clear();
    parent=tp;
    value=tv;
    iscand=false;
    child.pb(tp);
  }
  bool isvalid(int i){
    if (child[i] == NULL || child[i] == parent)return false;
    return true;
  }
  void del(Tree *now){
    rep(i,child.size()){
      if (now == child[i]){
	child.erase(child.begin()+i);
	i--;
      }
    }
  }
  int count_valid(){
    int cnt=0;
    rep(i,child.size()){
      if (isvalid(i))cnt++;
    }
    return cnt;
  }
};

int compute(int n){
  n = 3*n+1;
  while(n%2 == 0)n/=2;
  if (n > 12345678)n-=12345678;
  return n;
}

void update(Tree *now){
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    update(now->child[i]);
  }
  int tmp=now->value;
  now->value=compute(now->value);
  if (now->count_valid() ==0 && tmp < now->value)now->iscand=true;
  else now->iscand=false;
}


void get_all_death(Tree *now,vector<Tree*> &wildel){
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    get_all_death(now->child[i],wildel);
  }
  wildel.pb(now);
}

bool death(Tree *now,vector<Tree*> &wildel){
  if (now->value == 1){
    int cnt = 0;//count child
    Tree *ins=NULL;
    rep(i,now->child.size()){
      if (now->isvalid(i)){
	cnt++;
	ins=now->child[i];
      }
    }
    if (cnt == 1 && now->parent != NULL){
      now->parent->child.pb(ins);//because of chain
      ins->parent=now->parent;
      ins->del(now);
      ins->child.pb(now->parent);

      wildel.pb(now);
    }else get_all_death(now,wildel);
    return true;
  }

  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    if (death(now->child[i],wildel)){
      now->child.erase(now->child.begin()+i);
      i--;
    }
  }
  return false;//survive
}

void make_child(Tree *now){
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    make_child(now->child[i]);
  }
  
  if (now->iscand){
    int newvalue = (now->value+1)/2;
    if (newvalue%2 == 0)newvalue++;
    Tree *newnode;
    newnode = new Tree(newvalue,now);
    now->child.pb(newnode);
  }
}

void find_new_leader(Tree *now,int &maxval,int &maxcnt,Tree* &who){
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    find_new_leader(now->child[i],maxval,maxcnt,who);
  }
  
  if (now->value > maxval){
    maxval=now->value;
    maxcnt=1;
    who=now;
  }else if (now->value == maxval)maxcnt++;
}

void replace(Tree *now,Tree *parent){
  if (now == NULL)return;
  replace(now->parent,now);
  now->parent=parent;
}

Tree* find_leader(Tree *root){
  int maxval=0,maxcnt=0;
  Tree *who=NULL;
  find_new_leader(root,maxval,maxcnt,who);
  if (maxcnt == 1){
    replace(who,NULL);
    int newvalue = (who->value+1)/2;
    if (newvalue %2 == 0)newvalue--;

    Tree *bonus;
    bonus=new Tree(newvalue,who);
    who->child.pb(bonus);
    return who;
  }else return root;
}

void travarse(Tree *now){
  cout <<"I'm " << now->value <<" : " <<now <<" " <<  now->parent<<" : ";
  rep(i,now->child.size()){
    //if (!now->isvalid(i))continue;
    if (now->child[i] == now)continue;
    else if (now->child[i] != NULL)cout << now->child[i]->value <<",";
    else cout << now->child[i]<<",";
  }
  cout << endl;
  rep(i,now->child.size()){
    if (!now->isvalid(i))continue;
    travarse(now->child[i]);
  }
}


void del_travarse(Tree *now,vector<Tree*> &wildel){
  rep(i,now->child.size()){
   if (!now->isvalid(i))continue;
   del_travarse(now->child[i],wildel);
  }

  rep(i,wildel.size()){
    now->del(wildel[i]);
  }
}

bool operation_death(Tree *root){
  bool ret=false;
  vector<Tree*> wildel;
  if (death(root,wildel))ret=true;
  //  cout << wildel.size() << endl;
  del_travarse(root,wildel);
  rep(i,wildel.size())free(wildel[i]);
  return ret;
}

void count_node(Tree *now,int &cnt){
  cnt++;
  rep(i,now->child.size()){
   if (!now->isvalid(i))continue;
   count_node(now->child[i],cnt);
  }
}

void solve(int val){
  Tree *root;
  root=new Tree(val,NULL);
  int cnt=1;
  int maxnum=1;
  while(true){
    update(root);

    //    cout <<"update end"<<endl;
    //    travarse(root);cout << endl;

    if (operation_death(root))break;

    //cout <<"death end" << endl;
    //        travarse(root);cout << endl;

    make_child(root);
    //cout << "make_child end" << endl;
    //travarse(root);

    root = find_leader(root);


    int tmp = 0;
    count_node(root,tmp);
    maxnum=max(maxnum,tmp);
    //    cout <<"find leader end" << endl;
    //    travarse(root);cout << endl;
    //break;
    //if (cnt+1 == 105)travarse(root);
    cnt++;
  }
  
  cout << cnt <<" " << maxnum << endl;
  return;
}

main(){
  int n;
  while(cin>>n && n){
    //    cout <<"initial value is " << n << endl;
    solve(n);
  }
}
accuracy: 1
time_ms: 50
memory_kb: 1172
final_rank: 7