結論から言うと、答えは のとき 、のときは以下の式になります。
これは行列累乗を用いて で求まるため、十分高速です。
この式の気持ちについて説明しましょう。
まず 桁( )の条件を満たす数のうち、桁の寄与を一の位とそれ以外に分けました。
すると、一の位は必ず偶数でなければならないので、 のいずれかになります。
と を選ぶためには十の位以上の和が の倍数でなければなりません。同様に、 と を選ぶためには で 、を選ぶためには で である必要がありますが、十の位以上の桁の選び方のうち、 で となる選び方はいずれも 個になります。
よって、となります。
次に、十の位以上の寄与を考えていきましょう。" 桁であり、十の位以上を見たときに が となる数の十の位以上の部分"をすべて列挙した時の個数を 、それらのすべての桁の和を とおくと、以下の漸化式が成り立ちます。
これをそのまま行列で表現しても の行列累乗に帰着できるため十分高速ですが、 は によらず一定なので、その性質を用いると上に示した の行列に帰着することができます。
def matrixMultiplication(a,b,m): #行列の掛け算(a×b) m:mod
I,J,K,L = len(a),len(b[0]),len(b),len(a[0])
if(L!=K):
return -1
c = [[0] * J for _ in range(I)]
for i in range(I) :
for j in range(J) :
for k in range(K) :
c[i][j] += a[i][k] * b[k][j]
c[i][j] %= m
return c
def matrixExponentiation(x,n,m): #行列の累乗 (x^n) m:mod
y = [[0] * len(x) for _ in range(len(x))]
for i in range(len(x)):
y[i][i] = 1
while n > 0:
if n & 1:
y = matrixMultiplication(x,y,m)
x = matrixMultiplication(x,x,m)
n >>= 1
return y
mod = 10**9 + 7
t = int(input())
P = [
[4, 3, 3, 45],
[3, 4, 3, 45],
[3, 3, 4, 45],
[0, 0, 0, 10],
]
A = [[12], [15], [18], [3]]
for _ in range(t):
n = int(input())
if(n == 1):
print(6)
continue
Q = matrixExponentiation(P, n-2, mod)
V = matrixMultiplication(Q, A, mod)
ans = 60 * pow(10, n-2, mod) + 2* V[0][0] + V[1][0] + 2 * V[2][0]
print(ans % mod)
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
template<class T>
struct Matrix {
int _R , _C;
vector<vector<T>> val;
Matrix(int r, int c, T Val): val(r,vector<T>(c,Val)), _R(r), _C(c) {}
Matrix(int r, int c): Matrix(r, c, 0) {}
vector<T>& operator[](int i) {
return val[i];
}
Matrix operator*(const Matrix& other) {
assert(this->_C == other._R);
Matrix result(this->_R, other._C);
for (int i = 0; i < this->_R; i++) {
for (int j = 0; j < other._C; j++) {
for (int k = 0; k < this->_C; k++) {
result[i][j] += this->val[i][k] * other.val[k][j];
}
}
}
return result;
}
};
struct mint {
static const int mod = 1'000'000'007;
ll val;
mint(int k = 0): val((k % mod + mod) % mod) {}
mint operator*(const mint other) {return val * other.val % mod;}
mint& operator+=(const mint other) {
val = val + other.val >= mod? val + other.val - mod : val + other.val;
return *this;
}
};
Matrix<mint> pow_mat(Matrix<mint>a,ll n) {
int si = a[0].size();
Matrix<mint> res(si,si);
for (int i = 0; i < si; i++) res[i][i] = 1;
while (n > 0) {
if (n & 1) res = res * a;
a = a * a;
n >>= 1;
}
return res;
}
void solve(ll n) {
Matrix<mint> mat(4, 4);
mat[0] = {4, 3, 3, 45};
mat[1] = {3, 4, 3, 45};
mat[2] = {3, 3, 4, 45};
mat[3] = {0, 0, 0, 10};
Matrix<mint> dp(4, 1);
dp[0] = {18};
dp[1] = {12};
dp[2] = {15};
dp[3] = {3 };
dp = pow_mat(mat, n - 2) * dp;
mint ans = 0;
ans += dp[0][0] * 2;
ans += dp[1][0] * 2;
ans += dp[2][0] * 1;
ans += dp[3][0] * 20;
cout << ans.val << endl;
}
int main() {
int q;
cin >> q;
for (int i = 0; i < q; i++) {
ll n;
cin >> n;
if (n == 1)cout << 6 << endl;
else solve(n);
}
}