zoukankan      html  css  js  c++  java
  • LOJ6502「雅礼集训 2018 Day4」Divide

    https://loj.ac/p/6502

    考虑和 (w) 的顺序无关,那么可以把 (w) 排成一个更好 dp 的顺序
    若将 (w) 降序排列,那么对于每个 (i) 能使得 (w_i+w_jge m)(j) 是一个前缀,这看起来不错,但 dp 的话需要记录每个这样的前缀 ([1,j]) 中有几个在 A 集合,仍然不行

    但让这个前缀 ([1,j]=[1,i-1]) 是不现实的,所以可以尝试让 (j<i)(j) 要么都满足 (w_i+w_jge m),要么都满足 (w_i+w_j<m)
    考虑如何构造,若 (w_1+w_nge m),那么每个 (1le j<n) 都满足 (w_j+w_nge m),于是 (w_n) 置为新排列最后
    否则 (w_1) 置为新排列最后一样满足预设条件,递归到子问题

    所以就可以 (f_{i,j}) 表示前 (i) 个选了 (j) 个在 A 里面的答案了

    #define N 2006
    int n,m;
    int a[N],w[N];
    int ge[N];
    inline void pre(){
    	std::sort(a+1,a+1+n);
    	int l=1,r=n;
    	while(l<r){
    		if(a[l]+a[r]>=m) w[r-l+1]=a[r],ge[r-l+1]=1,r--;
    		else w[r-l+1]=a[l],l++;
    	}
    	w[1]=a[l];
    }
    #define mod 1000000007
    long long max[N][N],f[N][N];
    int main(){
    	n=read();m=read();
    	for(int i=1;i<=n;i++) a[i]=read();
    	pre();
    	std::memset(max,188,sizeof max);
    	max[1][0]=max[1][1]=0;f[1][0]=f[1][1]=1;
    	for(int i=1;i<n;i++){
    		for(int j=0;j<=i;j++){
    			long long now=max[i][j]+ge[i+1]*(i-j);
    			if(max[i+1][j+1]<now) f[i+1][j+1]=0,max[i+1][j+1]=now;
    			if(max[i+1][j+1]==now) f[i+1][j+1]=(f[i+1][j+1]+f[i][j])%mod;
    			now=max[i][j]+ge[i+1]*j;
    			if(max[i+1][j]<now) f[i+1][j]=0,max[i+1][j]=now;
    			if(max[i+1][j]==now) f[i+1][j]=(f[i+1][j]+f[i][j])%mod;
    		}
    	}
    	long long ans=0,num=0;
    	for(int j=0;j<=n;j++) ans=std::max(ans,max[n][j]);
    	for(int j=0;j<=n;j++)if(max[n][j]==ans) num=(num+f[n][j])%mod;
    	printf("%lld %lld
    ",ans,num);
    	return 0;
    }
    
  • 相关阅读:
    学习完vue指令 做的一个学生信息录入系统
    vue常用指令总结
    vue介绍以及相关概念理解大全
    class类
    javascript闭包详解
    前端必看网站(一直更新中)
    微信小程序wx.getUserInfo获取用户信息
    微信小程序自定义组件注意事项
    微信小程序自定义选项卡
    uni-app开发注意事项及常用样式
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/15395120.html
Copyright © 2011-2022 走看看