zoukankan      html  css  js  c++  java
  • BZOJ 1044: [HAOI2008]木棍分割

    Description

    求 (n) 根木棍长度为 (L) ,分成 (m) 份,使最长长度最短,并求出方案数.

    Sol

    二分+DP.

    二分很简单啊,然后就是方案数的求法.

    状态就是 (f[i][j]) 表示前 (i) 根木棍,分成 (j) 份的方案数.

    然后就是转移,我们发现这个转移是 (O(n)) 的,但他是一个前缀和的形式.

    因为决策点单调,我们可以用尺取法求出最远范围,然后用前缀和搞一下就可以了.

    空间开不下可以滚qwq.

    Code

    /**************************************************************
        Problem: 1044
        User: BeiYu
        Language: C++
        Result: Accepted
        Time:4912 ms
        Memory:2264 kb
    ****************************************************************/
     
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
     
    const int N = 50005;
    const int M = 1005;
    const int p = 10007;
     
    int n,m,l,r,t,mid,lim,ans;
    int a[N],b[N],c[N];
    int f[2][N];
     
    inline int in(int x=0,char ch=getchar()){ while(ch>'9'||ch<'0') ch=getchar();
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x; }
    int check(int x){
        int nd=0,tmp=0;
        for(int i=1;i<=n;i++) if(tmp+a[i]>x) tmp=a[i],nd++;else tmp+=a[i];
        if(tmp) nd++;
        return nd<=m;
    }
    int main(){
         
        n=in(),m=in()+1;
        for(int i=1;i<=n;i++) a[i]=in(),b[i]=b[i-1]+a[i],r+=a[i],l=max(l,a[i]);
         
        while(l<=r){
            mid=(l+r)>>1;
            if(check(mid)) r=mid-1;
            else l=mid+1;
        }cout<<l<<" ";
         
        lim=l,l=1,t=0;
         
        for(int i=1;i<=n;i++){
            t+=a[i];
            while(t>lim) t-=a[l++];
            c[i]=l;
        }
         
    //  for(int i=1;i<=n;i++) cout<<c[i]<<" ";cout<<endl;
         
        int cur=1;
        for(int i=0;i<=n;i++) f[0][i]=1;
        for(int i=1;i<=m;i++){
            memset(f[cur],0,sizeof(f[cur]));
            for(int j=1;j<=n;j++){
                f[cur][j]=((f[cur][j-1]+f[cur^1][j-1]-f[cur^1][c[j]-2])%p+p)%p;
            }ans=((ans+f[cur][n]-f[cur][n-1])%p+p)%p,cur^=1;
        }cout<<ans<<endl;
        return 0;
    }
    

      

  • 相关阅读:
    【递归】斐波那契数列第n个数
    二分查找【循环和递归】
    递归:正序、逆序输出一个正整数的各位数字
    Ubuntu x86-64汇编(5) 控制指令
    Ubuntu x86-64汇编(4) 数值操作指令
    Ubuntu x86-64汇编(3) 数值操作指令
    给X240换上了三键触摸板
    Ubuntu x86-64汇编(2)
    Ubuntu x86-64汇编(1)
    X240 Ubuntu18.04安装流水帐
  • 原文地址:https://www.cnblogs.com/beiyuoi/p/5943741.html
Copyright © 2011-2022 走看看