zoukankan      html  css  js  c++  java
  • CF1324E Sleeping Schedule 题解

    CSDN同步

    原题链接

    简要题意:

    每次可以将 (a_i)(1) 或不变。求让 (a_i) 的前缀和 (\% h) 的值在 ([l,r]) 区间中的最多的个数。

    E题是个水dp,也不怎样

    (f_{i,j}) 表示前 (i) 个数中,(igg ( sum_{k=1}^{i} a_k igg ) \% h = j) 的最大答案。

    显然,我们从第 (i) 个数入手。(下标出现负数的,在代码中均处理;转移方程中保留)

    如果不选,那么 (f_{i,j} = f_{i-1,j-a_i}).

    如果选,那么 (f_{i,j} = f_{i-1,j-a_i+1}).

    最后,(f_{i,j} gets f_{i,j} + (l leq j space exttt{and} space j<=r))

    这是因为,如果当前的这个前缀和在该范围,也算一个答案。

    所以:

    [ f_{i,j} = egin{cases} 0 , i=0 space exttt{and} space j=0 \ max{f_{i-1 , j-a_i} , f_{i-1,j-a_i+1}} \ end{cases} ]

    防止出现下标负数 (x) ,这样处理:

    [x gets (x+h) \%h ]

    如果 (x) 是正数,那 (+h) 不影响答案;如果 (x) 是负数,那 (+h) 变为正数,答案也正确。

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=2e3+1;
    
    inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
    
    int n,h,l,r,ans=0;
    int a[N],f[N][N];
    
    int main(){
    	n=read(),h=read(),l=read(),r=read();
    	for(int i=1;i<=n;i++) a[i]=read();
    	memset(f,-63,sizeof(f)); //预处理为极小值
    	f[0][0]=0;
    	for(int i=1;i<=n;i++)
    	for(int j=0;j<h;j++)
    		f[i][j]=max(f[i-1][(j-a[i]+h)%h],f[i-1][(j-a[i]+1+h)%h])+(l<=j && j<=r);
    	for(int i=0;i<h;i++) ans=max(ans,f[n][i]); //将 1~n 的答案取最大值
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    DRF简易了解
    Restful API接口规范
    Python分页
    vue笔记(一)
    CNN实现手写数字识别
    深度学习框架Keras
    NLP自然语言处理
    深度学习框架Tensorflow
    维度的区分
    矩阵求导
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12550615.html
Copyright © 2011-2022 走看看