數列 題解
阿新 • • 發佈:2020-07-15
題目描述
下面數列的第 n 項:
\(f(0) = a_0 ,f(1) = a_1 ,f(2) = a_2\)
\(f(n) = b×f(n − 1) + c×f(n − 2) + d×f(n − 3) + e (n ≥ 3)\)
輸入格式
包含 1 行,共 8 個整數:\(a_0、a_1、a_2、b、c、d、e、n\)。
輸出格式
輸出 f(n) 的後 18 位(後 18 位的字首 0 需要輸出,不足 18 位用 0 補齊)。
樣例輸入
1 2 3 4 5 6 7 3
樣例輸出
000000000000000035
資料範圍
對於 30% 的資料,\(0 ≤ a_0 ,a_1 ,a_2 ,b,c,d,e,n ≤ 10^6\)
對於 100% 的資料,\(0 ≤ a_0 ,a_1 ,a_2 ,b,c,d,e,n ≤ 10^{18}\)
沒有太多可分析的,直接來個示例程式碼吧
// 取最後18位的乘法計算 ll last18(ll x, ll y) { int a[25] = {0}, b[25] = {0}, c[25] = {0}; // 先處理兩個高精度的數 while (x || a[0] == 0) { a[++a[0]] = x % 10; x /= 10; } while (y || b[0] == 0) { b[++b[0]] = y % 10; y /= 10; } // 乘法只取後18位 for (int i = 1; i <= a[0]; ++i) { for (int j = 1; j <= b[0]; ++j) { if (i + j - 1 <= 18) { c[i + j - 1] += a[i] * b[j]; c[i + j] += c[i + j - 1] / 10; c[i + j - 1] %= 10; } } } // 最後再拼起來 ll ret = 0; for (int i = 18; i; --i) { ret = ret * 10 + c[i]; } return ret; } struct JZ { ll a[5][5]; void one() { memset(a, 0, sizeof(a)); for (int i = 1; i <= 4; ++i) a[i][i] = 1; } void init() { memset(a, 0, sizeof(a)); a[1][1] = b; a[1][2] = c; a[1][3] = d; a[1][4] = e; a[2][1] = a[3][2] = a[4][4] = 1; } void cheng(JZ &A) { // 矩陣乘法 JZ C; memset(C.a, 0, sizeof(C.a)); for (int i = 1; i <= 4; ++i) { for (int j = 1; j <= 4; ++j) { for (int k = 1; k <= 4; ++k) { C.a[i][j] = C.a[i][j] + last18(a[i][k], A.a[k][j]); if (C.a[i][j] >= mod) C.a[i][j] -= mod; } } } memcpy(a, C.a, sizeof(a)); } }; // 矩陣快速冪,求斐波那契數列用 JZ jzqpow(ll x) { JZ ret; ret.one(); JZ base; base.init(); while (x) { if (x & 1) { ret.cheng(base); } base.cheng(base); x >>= 1; } return ret; } // 最後的輸出 void print(ll x) { int a[20]; for (int i = 0; i < 18; ++i) { a[i] = x % 10; x /= 10; } for (int i = 17; i >= 0; --i) { printf("%d", a[i]); } }