【题目大意】
给出n个数,a[1]...a[n],称作集合S,求
其中f[i] = 2f[i-1] + 3f[i-2],给出f[0],f[1]。mod 99991
n<=100000
【题解】
暴力dp,用矩阵作为存储值,复杂度O(n^2)
# include <ctype.h> # include <stdio.h> # include <assert.h> # include <iostream> # include <string.h> # include <algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef long double ld; const int N = 1e5 + 10, M = 2e5 + 10; const int mod = 99991; inline int getint() { int x = 0, f = 1; char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') f = 0; ch = getchar(); } while(isdigit(ch)) { x = (x<<3) + (x<<1) + ch - '0'; ch = getchar(); } return f ? x : -x; } struct mat { int n, m, a[3][3]; inline void set(int _n, int _m) { n = _n, m = _m; memset(a, 0, sizeof a); } friend mat operator * (mat a, mat b) { mat c; c.set(a.n, b.m); assert(a.m == b.n); for (int i=1; i<=c.n; ++i) for (int j=1; j<=c.m; ++j) for (int k=1; k<=a.m; ++k) { c.a[i][j] += 1ll * a.a[i][k] * b.a[k][j] % mod; if(c.a[i][j] >= mod) c.a[i][j] -= mod; } return c; } friend mat operator ^ (mat a, ll b) { mat c; c.set(a.n, a.n); assert(a.n == a.m); for (int i=1; i<=c.n; ++i) c.a[i][i] = 1; while(b) { if(b&1) c = c * a; a = a * a; b >>= 1; } return c; } friend mat operator + (mat a, mat b) { assert(a.n == b.n && a.m == b.m); for (int i=1; i<=a.n; ++i) for (int j=1; j<=a.m; ++j) { a.a[i][j] += b.a[i][j]; if(a.a[i][j] >= mod) a.a[i][j] -= mod; } return a; } }A, T, U, g[2][5010], e[M]; inline int f(ll n) { if(n == 0) return A.a[1][1]; U = (T^(n-1)) * A; return U.a[2][1]; } int n, K, a[M]; inline void force() { int now = 1, pre = 0; for (int i=0; i<=1; ++i) for (int j=0; j<=n; ++j) g[i][j].set(2, 1); for (int i=1; i<=n; ++i) { g[now][0] = g[pre][0] = A; for (int j=1, jto = min(i, K); j<=jto; ++j) { g[now][j] = g[pre][j] + (e[i] * g[pre][j-1]); // printf("%d %d %d\n", i, j, g[i][j].a[1][1]); } swap(pre, now); } printf("%d\n", g[pre][K].a[1][1]); } int main() { // freopen("see.in", "r", stdin); // freopen("see.out", "w", stdout); n = getint(), K = getint(); for (int i=1; i<=n; ++i) a[i] = getint(); A.set(2, 1); T.set(2, 2); cin >> A.a[1][1] >> A.a[2][1]; T.a[2][1] = 3, T.a[2][2] = 2, T.a[1][1] = 0, T.a[1][2] = 1; for (int i=1; i<=n; ++i) e[i] = (T^a[i]); force(); return 0; } /* 4 2 1 2 1 3 1 1 20 10 125 3162 3261 152 376 238 462 4382 376 4972 16 1872 463 9878 688 308 125 236 3526 543 1223 3412 */