【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^3m\log n)\)的复杂度,\(w\)是矩阵大小;但是不难发现我们并不需要最后的矩阵,我们要的只是一个向量乘矩阵的结果,于是我们可以预处理所有矩阵的\(2\)次幂,拿一个向量直接乘过去就好了,由于向量乘矩阵的是\(O(w^2)\)的,所以复杂度是\(O(w^3\log n+w^2m\log 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\n",ans.v[2]); 
	return 0;
}
posted @ 2020-02-21 09:17  asuldb  阅读(227)  评论(0编辑  收藏  举报