zoukankan      html  css  js  c++  java
  • CF351C Solution

    题目链接

    简化题意

    构造一个长度为 (n imes m) 的合法括号序列。第 (i) 个位置上的左括号代价为 (a_{i mod n}),右括号代价为 (b_{i mod n})。求构造符合要求的括号序列的最小代价。

    题解

    首先,可以推出一个时间复杂度为 (O(n^2m)) 的dp。设 (dp_{i,j}) 表示前 (i) 个括号中有 (j) 个未匹配左括号时的最小代价,转移方程为 (dp_{i,j}=min(dp_{i-1,j-1}+a_i,dp_{i-1,j+1}+b_i)quad (ile ncdot m,jle n)) ,分别为第(i)个是左括号或右括号的情况。

    关于 (jle n) 的证明:设前 (i) 个括号中有 (j (j>n)) 个未匹配的左括号,易得 (i>n) ,也就是可以覆盖至少一个 (n) 循环。而 ([1,i]) 间左括号下标模 (n) 的不同余数个数一定 (>frac{n}{2}) ,否则每个 (n) 循环中左括号个数均 (le frac{n}{2}) ,不会有无法匹配的左括号。而 ([i+1,n]) 中一定有 (j) 个无法匹配的右括号,用以与 ([1,i]) 中未匹配的左括号匹配。所以同理, ([i+1,n]) 间右括号下标模 (n) 的不同余数个数一定 (>frac{n}{2}) ,否则没有无法匹配的右括号。所以 ([1,i]) 的左括号与 ([i+1,n]) 的右括号模 (n) 的余数有交集,一定存在一对模 (n) 同余左右括号可以互换位置,且代价不变。

    但是上述算法的时间不够优秀,考虑用矩阵快速幂加速dp。定义运算 ( imes) (不是矩阵乘法QwQ!), ((A imes B)_{i,j}=min(A_{i,k}+B_{k,j}))(A_{i,k}) 表示 (A) 矩阵的第 (i) 行第 (k) 个元素,下标从 (0) 开始)。为了可以使用矩快,需要证明 (A imes (B imes C)=(A imes B) imes C=D)(D_{i,j}=min(A_{i,k1}+min(B_{k1,k2}+C_{k2,j}))=min(min(A_{i,k1}+B_{k1,k2})+C_{k2,j})=min(A_{i,k1})+min(B_{k1,k2})+min(C_{k2,j})) 。而在本题中,易得转移矩阵: (egin{pmatrix}infty &b_{i\%n}&infty&cdots&infty \ a_{i\%n}&infty&b_{i\%n}&cdots&infty \ infty&a_{i\%n}&infty&cdots&infty \ cdots \ infty&infty&infty&cdots&infty end{pmatrix} imes egin{pmatrix} dp_{i-1,0} \ dp_{i-1,1} \ dp_{i-1,2} \ cdots \ dp_{i-1,n}end{pmatrix} = egin{pmatrix} dp_{i,0} \ dp_{i,1} \ dp_{i,2} \ cdots \ dp_{i,n}end{pmatrix}) ,第 (j) 行第 (j-1) 个为 (a_{i\%n}) ,第 (j) 行第 (j+1) 个为 (b_{i\%n}) ,其余为正无穷( (i\%n) 表示 (i)(n) 的余数)。设 (M_i) 表示以 (a_i,b_i) 组成的转移矩阵,则进一步化简后的答案为 ((M_0 imes M_1 imes cdots imes M_{n-1})^m_{0,0}) 。矩阵快速幂求值即可,时间复杂度为 (O(n^3log_m))

    代码

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=25,inf=2e9+1;//dp最大值可到2e9
    struct mat {int x[N][N];};
    int a[N],b[N],n;
    inline int read()
    {
    	int s=0,w=1; char ch=getchar();
    	while(ch<'0' || ch>'9') {if(ch=='-') w=-1; ch=getchar();}
    	while(ch>='0' && ch<='9') s=s*10+ch-'0',ch=getchar();
    	return s*w;
    }
    void init(mat &x)//初始化
    {
    	for(int i=1;i<=n+1;i++)
    		for(int j=1;j<=n+1;j++) x.x[i][j]=inf;
    }
    mat cal(mat x,mat y)//本题定义矩阵运算
    {
    	mat tmp; init(tmp);
    	for(int i=1;i<=n+1;i++)
    		for(int j=1;j<=n+1;j++)
    			for(int k=1;k<=n+1;k++) tmp.x[i][j]=min(tmp.x[i][j],x.x[i][k]+y.x[k][j]);
    	return tmp;
    }
    mat qpow(mat x,int y)//矩阵快速幂
    {
    	mat tmp; init(tmp);
    	bool flag=0;
    	while(y)
    	{
    		if(y&1)
    		{
    			if(flag) tmp=cal(tmp,x);
    			else tmp=x;//第一个无需进行取min运算
    			flag=1;
    		}
    		x=cal(x,x); y>>=1;
    	}
    	return tmp;
    }
    signed main()
    {
    	n=read(); int m=read();
    	for(int i=1;i<=n;i++) a[i]=read();
    	for(int i=1;i<=n;i++) b[i]=read();
    	mat res,tmp; init(tmp);//res:目标矩阵,tmp:转移矩阵
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n+1;j++) tmp.x[j][j-1]=a[i],tmp.x[j][j+1]=b[i];
    		if(i==1) res=tmp;//第一个无需进行取min运算
    		else res=cal(tmp,res);
    	}
    	res=qpow(res,m);
    	printf("%lld",res.x[1][1]);
    	return 0;
    }
    
  • 相关阅读:
    Android工具
    Android工具-DDMS
    Android ADB
    Windows FILETIME 与UNIX时间的转换
    <转>git,github在windows上的搭建
    国内的 Faas 云服务 -- Serverless 收集
    APICloud终于承认侵权并向DCloud道歉了(2019-11-26),知识产权!
    微信及钉钉等小程序开发的可视化工具
    C#的建造者设计模式(Builder),及Aspnet Core的源代码
    AspNet Core 3 的通用主机学习
  • 原文地址:https://www.cnblogs.com/violetholmes/p/15348468.html
Copyright © 2011-2022 走看看