您的位置:首页 > 其它

【bzoj4584】[Apio2016]赛艇 dp

2016-05-12 15:22 260 查看
首先,对区间离散化,最终会最多形成2n-1个区间

f[i][j][k]表示考虑到第i个学校,最后一个数落在j区间中,第j个区间中有k个数的方案数

sum[t]=∑f[i-1][j][p] (1<=j<t)

f[i][j][k]=f[i-1][j][k]+f[i-1][j][k-1]*(len[j]-k+1)/k

f[i][j][1]=f[i-1][j][1]+sum[j-1]*len[j]

前缀和优化一下就好了,考试的时候没有想清楚落在同一个区间中如何处理,所以导致最终思路偏了

可以优化空间,倒序枚举k即可

我该如何骂我自己好呢?

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 510
#define mod 1000000007

using namespace std;

struct yts
{
int l,r;
}q[maxn],seq[2*maxn];

int a[2*maxn];
int inv[1010];
int f[2*maxn][maxn],len[2*maxn];
int sum[2*maxn];
int dp[maxn][2*maxn];
int n,m,tot,num;

int query_l(int x)
{
int l=1,r=num,ans;
while (l<=r)
{
int mid=(l+r)/2;
if (x<=seq[mid].l) ans=mid,r=mid-1; else l=mid+1;
}
return ans;
}

int query_r(int x)
{
int l=1,r=num,ans;
while (l<=r)
{
int mid=(l+r)/2;
if (seq[mid].r<x) ans=mid,l=mid+1; else r=mid-1;
}
return ans;
}

int power(int x,int y)
{
int ans=1;
while (y)
{
if (y&1) ans=(long long)ans*x%mod;
x=(long long)x*x%mod;
y>>=1;
}
return ans;
}

int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
y++;
q[i].l=x;q[i].r=y;
a[++tot]=x;a[++tot]=y;
}
for (int i=1;i<=1000;i++) inv[i]=power(i,mod-2);
sort(a+1,a+tot+1);
for (int i=1;i<tot;i++)
if (a[i]!=a[i+1]) seq[++num].l=a[i],seq[num].r=a[i+1]-1,len[num]=a[i+1]-a[i];
for (int i=1;i<=n;i++) q[i].l=query_l(q[i].l),q[i].r=query_r(q[i].r);
for (int i=0;i<=num;i++) sum[i]=1;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=num;j++) dp[i][j]=dp[i-1][j];
for (int j=q[i].l;j<=q[i].r;j++) dp[i][j]++;
}
for (int i=1;i<=n;i++)
{
for (int j=q[i].l;j<=q[i].r;j++)
{
for (int k=dp[i][j];k>=2;k--)
f[j][k]=(f[j][k]+((long long)f[j][k-1]*(len[j]-k+1)%mod)*inv[k]%mod)%mod;
f[j][1]=(f[j][1]+(long long)sum[j-1]*len[j]%mod)%mod;
}
sum[0]=1;
for (int j=1;j<=num;j++)
{
sum[j]=sum[j-1];
for (int k=1;k<=dp[i][j];k++) sum[j]=(sum[j]+f[j][k])%mod;
}
}
int ans=0;
for (int i=1;i<=num;i++)
for (int j=1;j<=n;j++)
ans=(ans+f[i][j])%mod;
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: