【题目大意】

给出n个数,a[1]...a[n],称作集合S,求

「6月雅礼集训 2017 Day1」看无可看

其中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
*/
View Code

相关文章:

  • 2022-01-19
  • 2021-05-29
  • 2021-12-22
  • 2021-06-11
  • 2021-08-11
  • 2022-01-14
  • 2021-08-14
  • 2021-08-16
猜你喜欢
  • 2021-08-04
  • 2022-02-12
  • 2021-11-10
  • 2021-05-24
  • 2021-10-09
  • 2021-08-06
  • 2021-06-10
相关资源
相似解决方案