Problem:
MathJax.Hub.Config({
tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}
});

E: 28

問題文

トランプゲームの大富豪において，ランクが $2$, $8$ のカードは強力です．
そこで，$10$ 進数表記で数字の $2$, $8$ のみからなる整数を良い整数と呼ぶことにします．
良い整数を小さいものから列挙すると $2, 8, 22, 28, 82, 88, \cdots$ となります．

$n$ を正の整数とします．$n$ が良い整数の積の形で表現できるとき，
最大でいくつの積になるか求めてください．できないなら $-1$ と出力してください．

入力

$n$

制約

$1 \leq n \leq 10^{18}$

出力

答えを $1$ 行で出力してください．

サンプル

サンプル入力1

1

サンプル出力1

-1

サンプル入力2

2

サンプル出力2

1

サンプル入力3

88

サンプル出力3

3

$2 \times 2 \times 22$ と表せます．

サンプル入力4

100

サンプル出力4

-1

サンプル入力5

173553147234869248

サンプル出力5

11

$2^6 \times 28 \times 2222^3 \times 8828$ と表せます．

Solution in C (judge verdict: Accepted)

// AOJ 2769: 28
// 2018.1.6 bal4u@uu

#include <stdio.h>
#include <math.h>

#define HASHSIZ 1500019
typedef struct { long long p; char k; } HASH;
HASH hash[HASHSIZ+2], *hashend = hash+HASHSIZ;

int lookup(long long n)
{
	HASH *p = hash + (int)(n % HASHSIZ);
	while (p->p) {
		if (p->p == n) return p->k;
		if (++p == hashend) p = hash;
	}
	return 0;
}

void insert(long long n, char k)
{
	HASH *p = hash + (int)(n % HASHSIZ);
	while (p->p) {
		if (p->p == n) { p->k = k+1; return; }
		if (++p == hashend) p = hash;
	}
	p->p = n, p->k = k+1;
}

int sz;
long long p[524300];		// 2^19
int ans;

long long special[20] = {
8, 88, 888, 8888, 88888, 888888, 8888888, 88888888, 222888288,
888888888, 8888888888LL, 88888888888LL, 888888888888LL, 8888888888888LL,
88888888888888LL, 888888888888888LL, 8888888888888888LL,
88888888888888888LL, 888888888888888888LL, 0};

//#define getchar_unlocked()  getchar()
long long in()
{
	long long n = 0;
	int c = getchar_unlocked();
	do n = (n<<3)+(n<<1) + (c & 0xf), c = getchar_unlocked();
	while (c >= '0');
	return n;
}

int calc(long long n, int i, int s)
{
	int k, a, b;
	long long m;

	if (n & 1) return 0;
	if ((k = lookup(n)) > 0) { if (s+k > ans) ans = s+k; return 1; }
	if (n ==  4) { if (s+2 > ans) ans = s+2; return 1; }
	if (n == 16) { if (s+4 > ans) ans = s+4; return 1; }
	if (n < 21) return 0;

	b = (int)sqrt((double)n);
	for ( ; p[i] <= b; i++) {
		if (!p[i] || (n % p[i])) continue;
		k = (int)p[i];
		m = n / k, a = 1;
		while (!(m % k)) m /= k, a++;
		if (m == 1) { if (s+a > ans) ans = s+a; return 1; }
		if (m < k) m *= k, a--;
		while (a >= 0) {
			if (calc(m, i+1, s+a)) return 1;
			m *= k, a--;
		}
	}
	return 0;
}

void init()
{
	int i, j, k, k2;
	long long t;

	sz = 3;
	p[1] = 2, p[2] = 8, insert(2, 0), insert(8, 0);
	k = 1; for (i = 2; i <= 19; i++) {
		k2 = k << 1;
		for (j = k; j < k2; j++) {
			t = p[j]*10;
			t += 2, p[sz++] = t, insert(t, 0);
			t += 6, p[sz++] = t, insert(t, 0);
		}
		k = k2;
	}
	for (i = 0; special[i]; i++) insert(special[i], 2);
	insert( 1767928088070144LL, 7);
	insert(12751787892400128LL, 4);
	p[2] = p[6] = p[14] = 0;
}

int main()
{
	int k;
	long long n;

	init();
	n = in();
	if (n & 1) { puts("-1"); return 0; }
	if ((k = lookup(n)) > 0) { printf("%d\n", k); return 0; }
	k = 0; while (!(n & 1)) n >>= 1, k++;
	while (k >= 0) {
		n <<= 1, k--;
		calc(n, 2, k);
		if (ans > 0) { printf("%d\n", ans); break; }
	}
	if (ans <= 0) puts("-1");
	return 0;
}