zoukankan      html  css  js  c++  java
  • 【XR-1】分块

    题目link:https://www.luogu.com.cn/problem/P5343


    Part1:

    首先这道题能够想到一个比较显然的 $dp$ 。

    设 $dp[i]$ 表示长度为 $i$ 的序列有几种分块方式。

    那么容易的出转移方程: $dp[i]$ $=$ $∑$ $dp[i$ $-$ $p[j]]$ $(1$ $≤$ $j$ $≤$ $l)$ ,其中 $l$ 为相同长度的块数, $p[j]$ 表示第 $j$ 个相同长度的块。

    这样便可以 $O(n)$ 求出答案,可以通过 $60$$\%$ 的数据,但是 $100$$\%$ 的数据中 $0$ $≤$ $n$ $≤$ $10^{18}$ 。


    Part2:

    考虑优化,显然这个递推式是一个常系数线性递推,而这个 $l$ 的大小最大为 $100$ ,因此可以用矩阵快速幂优化。

    因此只需要预处理出前 $100$ 的 $dp$ 值,之后构造初始向量和转移矩阵就可以了。


    时间复杂度 $O($$x^3$ $*$ $log$ $k)$。


    Code:

      1 #include <cstdio>
      2 #include <algorithm>
      3 
      4 typedef long long LL;
      5 
      6 const int MAXN = 100;
      7 const LL MOD = 1e9 + 7;
      8 
      9 LL n, dp[MAXN + 5];
     10 int pr, nf, prPiece[MAXN + 5], nfPiece[MAXN + 5];
     11 int len, piece[MAXN + 5], x;
     12 
     13 struct Mat {
     14 
     15     int N, M;
     16     LL arr[MAXN + 5][MAXN + 5];
     17 
     18     Mat() {}
     19     Mat(int _N, int _M, LL val = 0ll) {
     20         N = _N, M = _M;
     21         for(int i = 1; i <= N; ++i) {
     22             for(int j = 1; j <= M; ++j) {
     23                 arr[i][j] = (i == j) ? val : 0ll;
     24             }
     25         }
     26     }
     27 
     28     // void print() {
     29     //     for(int i = 1; i <= N; ++i) {
     30     //         for(int j = 1; j <= M; ++j) {
     31     //             printf("%lld%c", arr[i][j], j == M ? '
    ' : ' ');
     32     //         }
     33     //     }
     34     //     puts("");
     35     // }
     36 
     37 };
     38 
     39 Mat operator* (const Mat &A, const Mat &B) {
     40 
     41     Mat res(A.N, B.M);
     42 
     43     for(int i = 1; i <= res.N; ++i) {
     44         for(int j = 1; j <= res.M; ++j) {
     45             for(int k = 1; k <= A.M; ++k) {
     46                 res.arr[i][j] += (A.arr[i][k] * B.arr[k][j]) % MOD;
     47                 res.arr[i][j] %= MOD;
     48             }
     49         }
     50     }
     51 
     52     return res;
     53 }
     54 
     55 Mat qpow(Mat A, LL k) {
     56 
     57     Mat res(A.N, A.M, 1);
     58 
     59     for(; k; k >>= 1) {
     60         if(k & 1) res = res * A;
     61         A = A * A;
     62     }
     63 
     64     return res;
     65 }
     66 
     67 int max(int a, int b) {
     68     return a > b ? a : b;
     69 }
     70 
     71 int main() {
     72 
     73     scanf("%lld", &n);
     74 
     75     scanf("%d", &pr);
     76     for(int i = 1; i <= pr; ++i) {
     77         scanf("%d", &prPiece[i]);
     78     }
     79 
     80     scanf("%d", &nf);
     81     for(int i = 1; i <= nf; ++i) {
     82         scanf("%d", &nfPiece[i]);
     83     }
     84 
     85     std::sort(prPiece + 1, prPiece + pr + 1);
     86     std::sort(nfPiece + 1, nfPiece + nf + 1);
     87     int ptPr = 1, ptNf = 1;
     88     while(ptPr <= pr && ptNf <= nf) {
     89         if(prPiece[ptPr] < nfPiece[ptNf]) {
     90             ++ptPr;
     91         }
     92         else if(prPiece[ptPr] > nfPiece[ptNf]) {
     93             ++ptNf;
     94         }
     95         else {
     96             if(prPiece[ptPr] != prPiece[ptPr - 1] && nfPiece[ptNf] != nfPiece[ptNf - 1]) {
     97                 piece[++len] = prPiece[ptPr];
     98             }
     99             ++ptPr, ++ptNf;
    100         }
    101     }
    102 
    103     for(int i = 1; i <= len; ++i) {
    104         x = max(x, piece[i]);
    105     }
    106 
    107     Mat fac(x, x), vec(1, x);
    108     dp[0] = 1ll;
    109     for(int i = 1; i <= x; ++i) {
    110         for(int j = 1; j <= len; ++j) {
    111             if(i - piece[j] < 0) break;
    112             dp[i] += dp[i - piece[j]];
    113             dp[i] %= MOD;
    114         }
    115     }
    116 
    117     for(int i = 1; i <= x; ++i) {
    118         vec.arr[1][i] = dp[x - i + 1];
    119     }
    120 
    121     for(int i = 1; i <= len; ++i) {
    122         fac.arr[piece[i]][1] = 1ll;
    123     }
    124 
    125     for(int i = 1; i <= fac.N; ++i) {
    126         for(int j = 2; j <= fac.M; ++j) {
    127             fac.arr[i][j] = (i == j - 1) ? 1ll : 0ll;
    128         }
    129     }
    130 
    131     if(n <= x) {
    132         printf("%lld
    ", dp[n]);
    133     }
    134     else {
    135         printf("%lld
    ", (vec * qpow(fac, n - x)).arr[1][1]);
    136     }
    137 
    138     return 0;
    139 }
  • 相关阅读:
    771. Jewels and Stones
    706. Design HashMap
    811. Subdomain Visit Count
    733. Flood Fill
    117. Populating Next Right Pointers in Each Node II
    250. Count Univalue Subtrees
    94. Binary Tree Inorder Traversal
    116. Populating Next Right Pointers in Each Node
    285. Inorder Successor in BST
    292. Nim Game Java Solutin
  • 原文地址:https://www.cnblogs.com/qqq1112/p/15060499.html
Copyright © 2011-2022 走看看