Official

D - Divide by 2 or 3 Editorial by m_99


\(a_i\) は、(素因数分解を考えると)非負整数 \(x_i,y_i\) 及び \(2\) でも \(3\) でも割り切れない正整数 \(z_i\) を用いて \(a_i=2^{x_i} \times 3^{y_i} \times z_i\) と一意に表すことが出来ます。ここで、\(2\) 種類の操作のうち前者は \(x_i\) を、後者は \(y_i\)\(1\) 減らすことに相当します。\(2\) でも \(3\) でも割り切れない正整数である \(z_i\) を変えることは出来ないため、\(z_i \neq z_j\) となる \(i,j\) が存在する場合の答えは -1 です。
\(x_i,y_i\) を増やすことは出来ないため、それぞれ \(x_i\) の最小値 \(x_m\)\(y_i\) の最小値 \(y_m\) に揃える必要があります。一方、最小値より小さな値に揃えるのは操作回数がより多く必要となるため無駄です。以上より、\(x_i,y_i\) をそれぞれ\(x_m,y_m\)に揃えるのに必要な回数を求めれば、すなわち \(x_i,y_i\)\(x_m,y_m\) の差の総和を求めれば答えを求められます。
下記実装例では初めに \(a_i\) の最大公約数 \(g\) を求め、\(\frac {a_i}{g}\) を考えて答えを求めています。( \(g=2^{x_m} \times 3^{y_m} \times z_i\) となることに気を付けてください)

実装例 (C++)

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

int main() {
    
	int N;
	cin>>N;
	
	vector<int> a(N);
	for(int i=0;i<N;i++){
		cin>>a[i];
	}
	
	int g = 0;
	for(int i=0;i<N;i++){
		g = gcd(g,a[i]);
	}
	
	int ans = 0;
	
	for(int i=0;i<N;i++){
		a[i] /= g;
		while(a[i]%2==0){
			a[i] /= 2;
			ans++;
		}
		while(a[i]%3==0){
			a[i] /= 3;
			ans++;
		}
		if(a[i]!=1){
			cout<<-1<<endl;
			return 0;
		}
	}
	
	cout<<ans<<endl;
	
	return 0;
}

posted:
last update: