• 【AGC013E】 Placing Squares


    题目

    模型转化;要是转化不出来就啥都不会了。

    这个(prod_{i=1}^ka_i^2)看起来并不好直接处理,我们考虑(a_i^2)的组合意义,就是把两个可区分的球放到(a_i)个可区分的盒子,允许一个盒子放多个的方案数;于是我们可以搞一个dp状物,设(f_{i,j})表示处理了前(i)个位置,当前这一段共放了(j)个球,转移的话就枚举一下这个位置放哪几个球,以及是否要另起一段,由于第二维只有(0/1/2),所以复杂度是(O(n))的。

    再来考虑一下关键点的限制,发现这个关键点的限制本质上就是使得这次转移不能另起一段,于是也很好处理。

    不难发现这两种转移都可以矩乘优化,由于两种转移的矩阵不一样,关键点个数只有(10^5)级别,所以我们用矩阵快速幂处理没有关键点的转移,就能做到(O(w^3mlog n))的复杂度,(w)是矩阵大小;但是不难发现我们并不需要最后的矩阵,我们要的只是一个向量乘矩阵的结果,于是我们可以预处理所有矩阵的(2)次幂,拿一个向量直接乘过去就好了,由于向量乘矩阵的是(O(w^2))的,所以复杂度是(O(w^3log n+w^2mlog n))。看起来好像没快多少,但少一个(w)就跑到了最优解。

    代码

    #include<bits/stdc++.h>
    #define re register
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    const int mod=1e9+7;const int maxn=1e5+5;
    int n,m,b[maxn];
    struct Vector{int v[3];}D,ans;
    struct Matrix{int a[3][3];}C,pw[32],G;
    inline int qm(int x) {return x>=mod?x-mod:x;}
    inline Matrix operator*(const Matrix &A,const Matrix &B) {
    	for(re int i=0;i<3;i++)
    		for(re int j=0;j<3;j++)C.a[i][j]=0;
    	for(re int k=0;k<3;k++)
    		for(re int i=0;i<3;i++)
    			for(re int j=0;j<3;j++)C.a[i][j]=qm(C.a[i][j]+1ll*A.a[i][k]*B.a[k][j]%mod);
    	return C;
    }
    inline Vector operator^(const Vector &A,const Matrix &B) {
    	for(re int i=0;i<3;i++)D.v[i]=0;
    	for(re int i=0;i<3;i++) 
    		for(re int j=0;j<3;j++)D.v[i]=qm(D.v[i]+1ll*A.v[j]*B.a[i][j]%mod);
    	return D;
    }
    inline void mul(int x) {
    	for(re int i=0;(1<<i)<=x;i++) 
    		if(x>>i&1) ans=ans^pw[i];
    }
    int main() {
    	n=read(),m=read();ans.v[0]=1;
    	for(re int i=1;i<=m;i++)b[i]=read();
    	std::sort(b+1,b+m+1);
    	for(re int i=0;i<3;i++)
    		for(re int j=0;j<3;j++) pw[0].a[i][j]=1;
    	pw[0].a[0][0]=pw[0].a[1][0]=2,pw[0].a[1][2]=0;
    	for(re int i=1;(1<<i)<=n;++i) pw[i]=pw[i-1]*pw[i-1];
    	G.a[1][0]=2;G.a[0][0]=G.a[1][1]=G.a[2][2]=G.a[2][0]=G.a[2][1]=1;
    	for(re int i=1;i<=m;i++) mul(b[i]-b[i-1]-1),ans=ans^G;
    	mul(n-b[m]);printf("%d
    ",ans.v[2]); 
    	return 0;
    }
    
  • 相关阅读:
    用Python操纵文件(自动化脚本的第一步)
    关于Numpy Array的使用技巧整理
    有用的在线小工具汇总
    HackerRank刷题之路---Python
    周志华老师《机器学习》复习要点(持续更新)
    Python函数式编程学习笔记
    Supervised Descent Method学习之路(持续更新)
    HackerRank刷题之路之---Algorithm(基于Python2)(持续更新)
    Vim常用命令精简化汇总及Vim的相关配置问题
    在VC++6.0中,如何将多个工程添加到同一个工作区?
  • 原文地址:https://www.cnblogs.com/asuldb/p/12340194.html
Copyright © 2020-2023  润新知