• [HAOI 2008]木棍分割


    Description

    题库链接

    (n) 根木棍,第 (i) 根木棍的长度为 (L_i)(n) 根木棍依次连结了一起,总共有 (n-1) 个连接处。现在允许你最多砍断 (m) 个连接处,砍完后 (n) 根木棍被分成了很多段,要求满足总长度最大的一段长度最小,并且输出有多少种砍的方法使得总长度最大的一段长度最小。对质数取模。

    (1leq nleq 50000,1leq mleq min{n-1,1000})

    Solution

    第一问二分,不再赘述。

    第二问考虑 (DP) 。令 (f_{i,j}) 为前 (i) 条木棍,划分为 (j) 段的方案数。转移我们考虑最后一段怎么分。我们可以预处理出一个数组 (pre_i) 表示最后一段最长能分到哪里,显然 [f_{i,j}=sum_{k=pre_i}^{i-1}f_{k,j-1}]

    显然这样复杂度是假的。我们可以用前缀和优化,并且珂以记 (f_{i}) 为当前枚举到分为 (j) 段时,第 (i) 条木棍前的方案数。这样直接省去一维。

    空间复杂度 (O(n)) ;时间复杂度 (O(nm))

    Code

    //It is made by Awson on 2018.3.3
    #include <bits/stdc++.h>
    #define LL long long
    #define dob complex<double>
    #define Abs(a) ((a) < 0 ? (-(a)) : (a))
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
    #define writeln(x) (write(x), putchar('
    '))
    #define lowbit(x) ((x)&(-(x)))
    using namespace std;
    const int N = 50000, INF = 5e8, yzh = 10007;
    void read(int &x) {
        char ch; bool flag = 0;
        for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
        for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
        x *= 1-2*flag;
    }
    void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
    void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); }
    
    int n, m, a[N+5], len, lef[N+5], f[N+5], s[N+5];
    
    bool judge(int x) {
        int cnt = 1, ret = 0;
        for (int i = 1; i <= n; i++) {
        if (a[i] > x) return false;
        if (ret+a[i] > x) ret = a[i], ++cnt; else ret += a[i];
        }
        return cnt <= m;
    }
    void solve1() {
        int l = 1, r = INF, ans;
        while (l <= r) {
        int mid = (l+r)>>1; if (judge(mid)) ans = mid, r = mid-1; else l = mid+1;
        }
        write(len = ans), putchar(' ');
    }
    void solve2() {
        int now = 0, ans = 0;
        for (int i = 1; i <= n; i++) {
        a[i] += a[i-1];
        while (a[i]-a[now] > len) ++now;
        lef[i] = now;
        }
        for (int i = 0; i <= n; i++) s[i] = 1;
        for (int len = 1; len <= m; len++) {
        for (int i = 1; i <= n; i++) f[i] = (lef[i] == 0 ? s[i-1] : s[i-1]-s[lef[i]-1]);
        s[0] = 0; for (int i = 1; i <= n; i++) s[i] = (f[i]+s[i-1])%yzh;
        ans = (ans+f[n])%yzh;
        }
        write((ans+yzh)%yzh);
    }
    void work() {
        read(n), read(m); ++m; for (int i = 1; i <= n; i++) read(a[i]);
        solve1(); solve2();
    }
    int main() {
        work(); return 0;
    }
  • 相关阅读:
    servlet配置restful
    Servlet异步上传文件
    JQuery全选Prop(“check”,true)和attr("attr",true)区别
    登录FTP,下载并读取文件内容
    Get请求中文乱码的几种解决方式
    系统架构概念及思想2
    系统架构概念及思想1
    Harbor高可用
    Harbor基础
    Docker原理及使用
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8496804.html
Copyright © 2020-2023  润新知