2 条题解
-
1
O_O怎么是构造题
原题:LOJ6502
首先我们容易考虑,设表示前个里面分个到队的方案数,然后直接转移。
但是我们无法计算新增加一头牛会增加多少答案,因为我们并不知道前头牛中有多少是的。
所以考虑构造一个的排列使得这个容易计算。
其实我觉得这里想到构造挺没道理的..
对于一段已排序的牛,若,则,这是一个良好的性质。我们可以让在的后面。
而若,则,我们也可以让在的后面,这样在计算时直接不造成贡献,也是良好的性质。
具体地,我们从开始考虑,若,则将放在栈顶,否则将放在栈顶,最后出栈就是一个具有良好性质的的排列。
在时,分类讨论时哪一种牛即可。
#include<bits/stdc++.h> using namespace std; #define int long long const int mod=1e9+7; int n,m,a[101000]; int b[101000],btt; int f[2020][2020],g[2020][2020]; signed main(){ cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+n+1); int l=1,r=n; for(int i=1;i<=n;i++){ if(a[r]+a[l]>=m) b[++btt]=a[r--]; else b[++btt]=a[l++]; } for(int i=1;i<=n/2;i++){ swap(b[i],b[n-i+1]); } f[0][0]=0; g[0][0]=1; for(int i=1;i<=n;i++){ for(int j=0;j<=i;j++){ if(b[i]+b[i-1]>=m){ if(j<=i-1) f[i][j]=f[i-1][j]+j; if(j) f[i][j]=max(f[i][j],f[i-1][j-1]+i-j); if(j<=i-1) if(f[i-1][j]+j==f[i][j]) g[i][j]+=g[i-1][j]; if(j) if(f[i-1][j-1]+i-j==f[i][j]) g[i][j]+=g[i-1][j-1]; }else{ if(j<=i-1)f[i][j]=f[i-1][j]; if(j) f[i][j]=max(f[i][j],f[i-1][j-1]); if(j<=i-1) if(f[i-1][j]==f[i][j]) g[i][j]+=g[i-1][j]; if(j) if(f[i-1][j-1]==f[i][j]) g[i][j]+=g[i-1][j-1]; } g[i][j]%=mod; } } int ans1=0,ans2=0; for(int i=1;i<=n;i++){ if(f[n][i]>ans1) ans1=f[n][i],ans2=0; if(f[n][i]==ans1) ans2+=g[n][i]; ans2%=mod; }cout<<ans1<<" "<<ans2; return 0; }
信息
- ID
- 285
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- (无)
- 递交数
- 72
- 已通过
- 4
- 上传者