【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;
}