# bzoj1044: [HAOI2008]木棍分割 二分+dp

/**************************************************************
Problem: 1044
User: walfy
Language: C++
Result: Accepted
Time:8564 ms
Memory:2264 kb
****************************************************************/

//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 10007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double eps=1e-6;
const int N=50000+10,maxn=5000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

int ans,dp[2][N];
int a[N],sum[N],n,m,last[N];
bool ok(int x)
{
int now=0,te=0;
for(int i=1;i<=n;i++)
{
if(now+a[i]<=x)now+=a[i];
else
{
te++;
now=a[i];
if(now>x)return 0;
}
}
if(te>m)return 0;
return 1;
}
void prepare()
{
int l=0,r=sum[n]+1;
while(l<r-1)
{
int m=(l+r)>>1;
if(ok(m))r=m;
else l=m;
}
ans=r;
for(int i=1;i<=n;i++)a[i]+=a[i-1];
}
void gao()
{
int now=0,pre=1,ans1=0;
dp[now][0]=1;
for(int i=1;i<=m+1;i++)
{
swap(now,pre);
memset(dp[now],0,sizeof dp[now]);
sum[0]=dp[pre][0];
for(int j=1;j<=n;j++)sum[j]=(sum[j-1]+dp[pre][j])%mod;
int k=0;
dp[now][0]=0;
for(int j=i;j<=n;j++)
{
while(a[j]-a[k]>ans)k++;
dp[now][j]=(sum[j-1]-(k?sum[k-1]:0))%mod;
dp[now][j]=(dp[now][j]+mod)%mod;
}
ans1=(ans1+dp[now][n])%mod;
}
printf("%d %d\n",ans,(ans1+mod)%mod);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
}
prepare();
gao();
return 0;
}
/********************
3 2
10 1 1
********************/
View Code

posted @ 2018-05-23 22:46  walfy  阅读(126)  评论(0编辑  收藏