1 条题解
-
0
「雅礼集训 2018 Day4」Divide 题解
很nb的构造
思路
考虑dp,设 表示前 艘飞船有 艘A队的飞船,但是如果直接转移发现我们记录的信息不够,难以转移。
那么此时假如记录更多信息,显然时间会超,所以我们考虑另一种方法——构造,构造出原 的一个合法排列,使得dp状态可以转移。
那么什么情况下可以转移?如果我们只记录 ,那么当前这艘飞船要么可以和全部的前 艘飞船匹配,即 ,要么不能和前 艘飞船匹配,即 。
考虑如下构造:
设构造后的数组为 ,先将 升序排序,初始设 ,然后进行 次比较:第 次比较,如果 ,则将 1 放到当前 的开头,即 ,否则 则将 0 放到 。
此时,对于一个 ,当 时表示它与前 个数无法匹配,当 时表示它可以与前 个数匹配。
证明:
假如当前 ,则新加的 ,由于 已经可以和 匹配,并且 是升序的,所以 都可以和 匹配,满足 的条件(前 个数就是 )。
假如当前 ,则新加的 ,由于 不能和 匹配,并且 是升序的,所以 都不可以和 匹配,满足 的条件(前 个数就是 )。
证毕。
那么此时按新排列的 进行转移就是容易的。
当第 艘飞船加入A队时,。
当第 艘飞船加入B队时,。
最后统计方案数 就是取两者中较大的,如果相同就都加起来。
代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int mod=1e9+7; int n,m,a[2010],p[2010]; ll f[2010][2010],g[2010][2010]; int main(){ ios::sync_with_stdio(0); cin.tie(0); cin>>n>>m; for(int i=1;i<=n;i++)cin>>a[i];//就是w_i sort(a+1,a+1+n); int l=1,r=n; for(int i=n;i;i--){//构造p_i if(a[l]+a[r]>=m){ r--;p[i]=1; } else{ l++;p[i]=0; } } g[0][0]=1; for(int i=1;i<=n;i++){//简单的dp for(int j=0;j<=i;j++){ if(j){ ll v=f[i-1][j-1]+p[i]*(i-j); if(v>f[i][j]){ f[i][j]=v; g[i][j]=g[i-1][j-1]; } else if(v==f[i][j])g[i][j]=(g[i][j]+g[i-1][j-1])%mod; } if(j<i){ ll v=f[i-1][j]+p[i]*j; if(v>f[i][j]){ f[i][j]=v; g[i][j]=g[i-1][j]; } else if(v==f[i][j])g[i][j]=(g[i][j]+g[i-1][j])%mod; } } } ll ans=0,cnt=0; for(int i=0;i<=n;i++){ if(f[n][i]>ans){ ans=f[n][i];cnt=g[n][i]; } else if(f[n][i]==ans)cnt=(cnt+g[n][i])%mod; } cout<<ans<<" "<<cnt; return 0; }
- 1
信息
- ID
- 10118
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 9
- 标签
- 递交数
- 16
- 已通过
- 3
- 上传者