• [HAOI2008]木棍分割


    题目描述

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

    输入输出格式

    输入格式:

    输入文件第一行有2个数n,m. 接下来n行每行一个正整数Li,表示第i根木棍的长度.

    输出格式:

    输出有2个数, 第一个数是总长度最大的一段的长度最小值, 第二个数是有多少种砍的方法使得满足条件.

    输入输出样例

    输入样例#1: 复制
    3 2                           
    1 
    1
    10
    输出样例#1: 复制
    10 2

    说明

    两种砍的方法: (1)(1)(10)和(1 1)(10)

    数据范围

    n<=50000, 0<=m<=min(n-1,1000).

    1<=Li<=1000.

    第一问二分答案

    第二问dp

    $f[i][j]$表示前i个点,断j次

    显然$f[i][j]=sum_k^{}f[k][j-1]$

    k满足sum[i]-sum[k-1]<=ans

    这个k随着i增大而增大,所以可以单调

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 typedef long long lol;
     8 int L[50001],ans;
     9 int f[50001],sum[50001],res;
    10 int n,m,Mod=10007;
    11 int check(lol mid)
    12 {int i;
    13   int now=0,cnt=0;
    14   for (i=1;i<=n;i++)
    15     {
    16       if (L[i]-L[i-1]>mid) return m+1;
    17       int j=i;
    18       while (j<=n&&L[j]-L[i-1]<=mid) j++;
    19       cnt++;
    20       if (cnt-1>m) return m+1;
    21       i=j-1;
    22     }
    23   return cnt-1;
    24 }
    25 int main()
    26 {int i,j;
    27   cin>>n>>m;
    28   for (i=1;i<=n;i++)
    29     {
    30       scanf("%d",&L[i]);
    31       L[i]+=L[i-1];
    32     }
    33   int l=1,r=L[n];
    34   while (l<=r)
    35     {
    36       int mid=(l+r)>>1;
    37       if (check(mid)<=m) ans=mid,r=mid-1;
    38       else l=mid+1;
    39     }
    40   cout<<ans<<' ';
    41   for (i=1;i<=n;i++)
    42     if (L[i]<=ans) f[i]=1;
    43   if (L[n]<=ans) res=1;
    44   else res=0;
    45   for (i=1;i<=m;i++)
    46     {
    47       for (j=1;j<=n;j++)
    48     {
    49       sum[j]=(f[j]+sum[j-1]);
    50       if (sum[j]>=Mod) sum[j]-=Mod;
    51       f[j]=0;
    52     }
    53       int l=1;
    54       for (j=i+1;j<=n;j++)
    55     {
    56       while (l<=j&&L[j]-L[l-1]>ans) l++;
    57       f[j]=(sum[j-1]-sum[l-2]+Mod);
    58       if (f[j]>=Mod) f[j]-=Mod;
    59     }
    60       res=(res+f[n]);
    61       if (res>=Mod) res-=Mod;
    62     }
    63   cout<<res;
    64 }
  • 相关阅读:
    [转]asp.net core中的View Component
    [转] 三层架构、MVC
    [转]Javascript异步编程之三Promise: 像堆积木一样组织你的异步流程
    T4语法快速入门
    [转]ASP.NET Core 十种方式扩展你的 Views
    (装机)关于WINRE/ESP/LRS_ESP/MSR/PBR这些分区
    C#设计模式系列目录
    [转]RESTful API 设计指南
    .gitignore释疑
    [转]Subdirectory Checkouts with git sparse-checkout
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8482957.html
Copyright © 2020-2023  润新知