zoukankan      html  css  js  c++  java
  • JXOI2017 数列

    数列

    九条可怜手上有一个长度为 (n) 的整数数列 (r_i) ,她现在想要构造一个长度为 (n) 的,满足如下条件的整数数列 (A)

    • (1leq A_i leq r_i)
    • 对于任意 (3 leq i leq n),令 (R)(A_1)(A_{i-2}) 中大于等于 (A_{i-1}) 的最小值,(L)(A_1)(A_{i-2}) 中小于等于 (A_{i-1}) 的最大值。(A_i) 必须满足 (L leq A_i leq R)。如果不存在大于等于 (A_{i-1}) 的,那 么 (R = +infty);如果不存在小于等于 (A_{i-1}) 的,那么 (L = −infty)

    现在可怜想要知道共有多少不同的数列满足这个条件。两个数列 (A)(B) 是不同的当且仅当至少存在一个位置 (i) 满足 (A_i eq B_i)

    (nleq 50,rleq 150)

    题解

    http://jklover.hs-blog.cf/2020/06/06/Loj-2273-数列/#more

    dp 计数.

    不难发现,合法的选择区间会在选一个数之后不断收缩,将它作为状态记录下来 dp 即可.

    (dp(i,l,r,k)) 表示考虑了前 (i) 个数,下个数合法的选择区间为 ([l,r]) , 最后一个数的值为 (k) 的方案数.

    转移时,对于 ([l,l],[l+1,k-1],[k,k],[k+1,r-1],[r,r]) 这几段分别转移,每一段内转移到新的 (l,r) 是一样的.

    于是修改差分就可以完成 (O(1)) 转移,注意处理 (l,r) 不存在等特殊情况,时间复杂度 (O(ncdot r^3)) .

    CO int N=160;
    int t[N],f[2][N][N][N];
    
    IN void trans(int o,int l,int r,int L,int R,int v){ // k in [L,R]
    	if(L>R) return;
    	f[o][l][r][L]=add(f[o][l][r][L],v),f[o][l][r][R+1]=add(f[o][l][r][R+1],mod-v);
    }
    int main(){
    	int n=read<int>(),m=0;
    	for(int i=1;i<=n;++i) m=max(m,read(t[i]));
    	int o=0,bound=t[1];
    	f[o][0][m+1][1]=1,f[o][0][m+1][bound+1]=mod-1;
    	for(int i=2;i<=n;++i){
    		for(int l=0;l<=m+1;++l)for(int r=l;r<=m+1;++r)
    			for(int k=l;k<=r;++k) f[o][l][r][k]=add(f[o][l][r][k],f[o][l][r][k-1]);
    		o^=1,bound=t[i];
    		for(int l=0;l<=m+1;++l)for(int r=l;r<=m+1;++r)
    			for(int k=l;k<=r;++k) f[o][l][r][k]=0;
    		for(int l=0;l<=m+1;++l)for(int r=l;r<=m+1;++r)
    			for(int k=l;k<=r;++k)if(f[o^1][l][r][k]){
    				int L=max(l,1),R=min(l,bound);
    				trans(o,l,l,L,R,f[o^1][l][r][k]);
    				L=max(l+1,1),R=min(k-1,bound);
    				trans(o,l,k,L,R,f[o^1][l][r][k]);
    				if(k>l){
    					L=max(k,1),R=min(k,bound);
    					trans(o,k,k,L,R,f[o^1][l][r][k]);
    				}
    				L=max(k+1,1),R=min(r-1,bound);
    				trans(o,k,r,L,R,f[o^1][l][r][k]);
    				if(r>k){
    					L=max(r,1),R=min(r,bound);
    					trans(o,r,r,L,R,f[o^1][l][r][k]);
    				}
    			}
    	}
    	int ans=0;
    	for(int l=0;l<=m+1;++l)for(int r=l;r<=m+1;++r)
    		for(int k=l;k<=r;++k){
    			f[o][l][r][k]=add(f[o][l][r][k],f[o][l][r][k-1]);
    			ans=add(ans,f[o][l][r][k]);
    		}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    1-直播转点播
    3-美团 HTTP 服务治理实践
    3-SSDB 高性能NoSQL数据库, 用于替代 Redis.
    配置kubectl在Mac(本地)远程连接Kubernetes集群
    4-rocketmq 发送时异常:system busy 和 broker busy 解决方案
    3-RocketMQ 简单梳理 及 集群部署笔记
    2-Rocketmq产品架构(参考阿里云)
    1-RocketMq 学习 中文文档(一)
    tar命令参数详解
    Ubuntu 安装 .bundle 文件
  • 原文地址:https://www.cnblogs.com/autoint/p/13150425.html
Copyright © 2011-2022 走看看