← Home
For problem statement at 0-999/400-499/490-499/498/problemE.txt this is a correct solution, but verifier at 0-999/400-499/490-499/498/verifierE.go ends with All tests passed can you fix the verifier? package main

import (
	"bufio"
	"fmt"
	"os"
)

const MOD int64 = 1000000007

func buildCounts(h int) []int64 {
	n := 1 << h
	res := make([]int64, n)
	for c := 0; c < n; c++ {
		var dp0, dp1 int64 = 0, 1
		for y := 0; y < h-1; y++ {
			if (c>>y)&1 == 1 {
				nd0 := dp0 + dp1
				nd1 := dp0
				dp0, dp1 = nd0, nd1
			} else {
				s := dp0 + dp1
				dp0, dp1 = s, s
			}
		}
		if (c>>(h-1))&1 == 1 {
			res[c] = dp0
		} else {
			res[c] = dp0 + dp1
		}
	}
	return res
}

func buildMatrix(cnt []int64, h int) []int64 {
	n := 1 << h
	m := make([]int64, n*n)
	for l := 0; l < n; l++ {
		off := l * n
		for r := 0; r < n; r++ {
			m[off+r] = cnt[l&r]
		}
	}
	return m
}

func vecMul(vec, mat []int64, rows, cols int) []int64 {
	res := make([]int64, cols)
	for i := 0; i < rows; i++ {
		vi := vec[i]
		if vi == 0 {
			continue
		}
		off := i * cols
		for j := 0; j < cols; j++ {
			res[j] = (res[j] + vi*mat[off+j]) % MOD
		}
	}
	return res
}

func matMul(a, b []int64, n int) []int64 {
	c := make([]int64, n*n)
	for i := 0; i < n; i++ {
		aiOff := i * n
		ciOff := i * n
		for j := 0; j < n; j++ {
			av := a[aiOff+j]
			if av == 0 {
				continue
			}
			bjOff := j * n
			for k := 0; k < n; k++ {
				c[ciOff+k] = (c[ciOff+k] + av*b[bjOff+k]) % MOD
			}
		}
	}
	return c
}

func applyPow(vec, base []int64, n, exp int) []int64 {
	mat := base
	for exp > 0 {
		if exp&1 == 1 {
			vec = vecMul(vec, mat, n, n)
		}
		exp >>= 1
		if exp > 0 {
			mat = matMul(mat, mat, n)
		}
	}
	return vec
}

func transUp(vec []int64, h1, h2 int, cnt []int64) []int64 {
	n1 := 1 << h1
	n2 := 1 << h2
	res := make([]int64, n2)
	ext := ((1 << (h2 - h1)) - 1) << h1
	for l := 0; l < n1; l++ {
		vl := vec[l]
		if vl == 0 {
			continue
		}
		lext := l | ext
		for r := 0; r < n2; r++ {
			res[r] = (res[r] + vl*cnt[lext&r]) % MOD
		}
	}
	return res
}

func main() {
	in := bufio.NewReader(os.Stdin)
	w := make([]int, 8)
	for i := 1; i <= 7; i++ {
		fmt.Fscan(in, &w[i])
	}

	counts := make([][]int64, 8)
	mats := make([][]int64, 8)
	for h := 1; h <= 7; h++ {
		counts[h] = buildCounts(h)
		mats[h] = buildMatrix(counts[h], h)
	}

	first := 0
	for i := 1; i <= 7; i++ {
		if w[i] > 0 {
			first = i
			break
		}
	}

	n := 1 << first
	vec := make([]int64, n)
	vec[n-1] = 1
	vec = applyPow(vec, mats[first], n, w[first])

	prev := first
	for h := first + 1; h <= 7; h++ {
		if w[h] == 0 {
			continue
		}
		vec = transUp(vec, prev, h, counts[h])
		if w[h] > 1 {
			vec = applyPow(vec, mats[h], 1<<h, w[h]-1)
		}
		prev = h
	}

	out := bufio.NewWriter(os.Stdout)
	fmt.Fprintln(out, vec[(1<<prev)-1]%MOD)
	out.Flush()
}