这是一个水题
然而我却想了一年
我好菜啊
这个题分为两问
第一问随便二分
第二份随便 d p
然而简简单单的 d p 会 T 而且 M
所以使用滚动数组解决M的问题
然后发现每一个点向前追溯的点是一样的所以可以预处理
然后搞一搞前缀和就好啦!
#include<bits/stdc++.h>
using namespace std;
const int MX = 50005 ;
const int mod = 10007 ;
int n,m,a[MX],tot,pos[MX],sum[2][MX],f[2][MX],cur,las,ans;
bool judge(int len)
{
int sum=0,cnt=0;
for(int i=1;i<=n;i++)
{
if(a[i]>len) return false;
sum+=a[i];
if(sum>len) sum=a[i],cnt++;
}
if(cnt>m) return false;
else return true;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int l=1,r=50000000;
while(l<r)
{
int mid=(l+r)>>1;
if(judge(mid)) r=mid;
else l=mid+1;
}
printf("%d ",l);
int k=0;
for(int i=1;i<=n;i++)
{
tot+=a[i];
while(tot>l) tot-=a[k],k++;
pos[i]=k-1;
}
tot=0;
for(int i=1;i<=n;i++)
{
tot+=a[i];
if(tot<=l) f[1][i]=1;
sum[1][i]=sum[1][i-1]+f[1][i];
}
for(int i=1;i<=m;i++)
{
las=i&1;
cur=las^1;
for(int j=1;j<=n;j++)
f[cur][j]=(sum[las][j-1]-sum[las][max(pos[j]-1,0)]+mod)%mod,sum[cur][j]=(sum[cur][j-1]+f[cur][j])%mod;
ans=(ans+f[cur][n])%mod;
}
printf("%d\n",ans);
}
心得:
1.我的dp非常菜
2.滚动数组要会
3.追溯点固定可以前缀和