zoukankan      html  css  js  c++  java
  • LOJ3247 Non-Decreasing Subsequences

    Non-Decreasing Subsequences

    Bessie 最近参加了一场 USACO 竞赛,遇到了以下问题。当然 Bessie 知道怎么做。那你呢?

    考虑一个仅由范围在 (1ldots K) 之间的整数组成的长为 (N) 的序列 (A_1,A_2,ldots ,A_N)。给定 (Q) 个形式为 ([L_i,R_i]) 的询问。对于每个询问,计算 (A_{L_i},A_{L_{i+1}},ldots ,A_{R_i}) 中不下降子序列的数量模 (10^9+7) 的余数。

    (A_L,ldots ,A_R) 的一个不下降子序列是一组索引 ((j_1,j_2,ldots ,j_x)),满足 (Lle j_1<j_2<ldots <j_xle R) 以及 (A_{j_1}le A_{j_2}le ldots le A_{j_x})。确保你考虑了空子序列!

    对于全部数据,(1le Kle 20,1le Nle 5 imes 10^4,1le Qle 2 imes 10^5,1le L_ile R_ile N)

    题解

    http://jklover.hs-blog.cf/2020/06/06/Loj-3247-Non-Decreasing-Subsequences/
    https://www.luogu.com.cn/blog/Karry5307/sol-p6009

    矩阵乘法.

    dp 显然可以写成转移矩阵的形式.

    (v) 为长度为 (K) ,值全为 (1) 的列向量, (w) 为长度为 (K) ,仅第一个值为 (1) 的行向量, (T_i) 表示第 (i) 个数对应的转移矩阵.

    那么询问 ([l,r]) 的答案就是

    [(w(prod_{i=l}^r T_i)v)_{0,0} ]

    (r) 个位置的转移矩阵大概长这样:

    [T_{r,i,j}=[i=j]+[ileq j][j=a_r] ]

    注意到转移矩阵 (T_i) 有逆,且逆是容易直接求出的,于是可以考虑维护转移矩阵前缀积,以及逆矩阵的前缀积.

    考虑这个东西的逆矩阵是啥。根据人类智慧得到

    [T_{r,i,j}^{-1}=[i=j]-frac{1}{2}[ileq j][j=a_r] ]

    (x_i=T_1T_2T_3cdots T_iv,y_i=wT_{i}^{-1}cdots T_{3}^{-1}T_2^{-1}T_1^{-1}) ,则询问的答案为 ((y_{l-1}x_r)_{0,0}) .

    (T_i)(T_{i}^{-1}) 都只有 (O(k)) 个位置有值,于是右乘 (T_{i}) 与左乘 (T_{i}^{-1}) 都可以 (O(K^2)) 完成.

    时间复杂度 (O(nK^2+qK)) .

    CO int N=5e4+10;
    int K,a[N],op;
    struct matrix {int v[20][20];} x[N],y[N];
    
    matrix operator*(CO matrix&a,CO matrix&b){
    	matrix ans={};
    	if(!op){
    		for(int k=0;k<K;++k)
    			for(int j=0;j<K;++j)if(b.v[k][j])
    				for(int i=0;i<K;++i)if(a.v[i][k])
    					ans.v[i][j]=add(ans.v[i][j],mul(a.v[i][k],b.v[k][j]));
    	}
    	else{
    		for(int k=0;k<K;++k)
    			for(int i=0;i<K;++i)if(a.v[i][k])
    				for(int j=0;j<K;++j)if(b.v[k][j])
    					ans.v[i][j]=add(ans.v[i][j],mul(a.v[i][k],b.v[k][j]));
    	}
    	return ans;
    }
    
    int main(){
    	int n=read<int>();read(K);
    	for(int i=1;i<=n;++i) a[i]=read<int>()-1;
    	
    	op=0;
    	for(int i=0;i<K;++i) x[0].v[i][i]=1;
    	for(int i=1;i<=n;++i){
    		matrix tmp={};
    		for(int j=0;j<K;++j) tmp.v[j][j]=1;
    		for(int j=0;j<=a[i];++j) ++tmp.v[j][a[i]];
    		x[i]=x[i-1]*tmp;
    	}
    	matrix tmp={};
    	for(int i=0;i<K;++i) tmp.v[i][0]=1;
    	for(int i=1;i<=n;++i) x[i]=x[i]*tmp;
    	
    	op=1;
    	for(int i=0;i<K;++i) y[0].v[i][i]=1;
    	for(int i=1;i<=n;++i){
    		matrix tmp={};
    		for(int j=0;j<K;++j) tmp.v[j][j]=1;
    		for(int j=0;j<=a[i];++j) tmp.v[j][a[i]]+=mod-i2;
    		y[i]=tmp*y[i-1];
    	}
    	memset(tmp.v,0,sizeof tmp);
    	tmp.v[0][0]=1;
    	for(int i=1;i<=n;++i) y[i]=tmp*y[i];
    	
    	for(int q=read<int>();q--;){
    		int l=read<int>(),r=read<int>(),ans=0;
    		for(int k=0;k<K;++k)
    			ans=add(ans,mul(y[l-1].v[0][k],x[r].v[k][0]));
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    POJO,简单的Java对象
    Oracle 11g R2 for Win7旗舰版(64位)- 安装
    Eclipse安装与配置
    Tomcat 安装、配置与部署
    图形数据库 Neo4j 开发实战【转载】
    Java 语言中 Enum 类型的使用介绍【转载】
    IBM Java 7 新特性和在 WAS 8.5 中的配置【转载】
    为Eclipse指定JVM
    网页页面的宽度:950 还是 960?
    Zabbix + Grafana
  • 原文地址:https://www.cnblogs.com/autoint/p/13150319.html
Copyright © 2011-2022 走看看