1 条题解
-
0
不妨先考虑一个朴素的 dp。记 表示已经考虑到第 列,并且格子可以使用情况为 (认为 是可以使用), 表示第 行可以摆放的情况。
考虑 对第 行的状态可以有哪些贡献:
-
摆放横着的瓷砖:如果放在第 行,则要求 和 的第 个二进制位上都是 ;注意,可以不止放一个横着的瓷砖,也可以不仅放横着的瓷砖。
-
摆放竖着的瓷砖:如果放在第 行,则要求 的第 个二进制位上都是 ;
那么考虑枚举在哪些行放横着的瓷砖 ,如果合法(即 和 , 无交),就进行转移;在此基础上,判断能否放竖着的瓷砖,如果可以就转移。
初始状态为 ,因为在第一列不能利用上一列的空位。
上面的时间复杂度为 ,其中 是状态数,为 。常数良好可以轻松通过第 个子任务。
考虑第二个子任务。因为只有一种状态,那么无论询问区间是什么,答案之和区间长度有关,因此可以预处理每一个区间长度的答案。
因为转移是固定的,且状态数较少,所以考虑 ddp。预处理每一个 的取值对于的转移矩阵,然后用线段树进行询问和修改,时间复杂度为 。
const int N=3e4+500,p=1e9+7; const ull MX=2e9; inline int bmod(int x){return x>=p ? x-p : x;} inline void add(int &x,int y){x=bmod(x+y);} inline int qpow(int x,int y){ int res=1; for(;y;y>>=1,x=1ull*x*x%p) if(y&1) res=1ull*x*res%p; return res; } int n,m,a[N]; char s[N]; struct Matrix{ int n,m; ull a[10][10]; Matrix(int _n=8,int _m=8){ n=_n,m=_m; for(int i=0;i<n;++i) for(int j=0;j<m;++j) a[i][j]=0; } Matrix operator *(const Matrix x) const{ Matrix res=Matrix(n,x.m); for(int i=0;i<n;++i) for(int k=0;k<m;++k){ ull v=a[i][k]; for(int j=0;j<x.m;++j) res.a[i][j]+=v*x.a[k][j]; } for(int i=0;i<n;++i) for(int j=0;j<x.m;++j) res.a[i][j]=(res.a[i][j]>=MX ? res.a[i][j]%p : res.a[i][j]); return res; } }init_mat[10],mat[N<<2],Res; struct Tree{int l,r;}t[N<<2]; void push_up(int i){ mat[i]=mat[ls]*mat[rs]; } void build(int i,int l,int r){ t[i].l=l,t[i].r=r; if(l==r){ mat[i]=init_mat[a[l]]; return; } int mid=t[i].l+t[i].r>>1; build(ls,l,mid); build(rs,mid+1,r); push_up(i); } void update(int i,int x){ if(t[i].l==t[i].r){ mat[i]=init_mat[a[x]]; return; } int mid=t[i].l+t[i].r>>1; if(x<=mid) update(ls,x); else update(rs,x); push_up(i); } void query(int i,int l,int r){ if(l<=t[i].l && t[i].r<=r){ Res=Res*mat[i]; return; } int mid=t[i].l+t[i].r>>1; if(l<=mid) query(ls,l,r); if(mid<r) query(rs,l,r); } int main() { n=read(),m=read(); For(i,0,2){ scanf("%s",s+1); For(j,1,n) a[j]|=(s[j]=='x')*(1<<i); } For(i,0,7){ init_mat[i]=Matrix(8,8); For(j,0,7){ For(k,0,7){ if((i&k) || (j&k)) continue; int nw=(i|k); ++init_mat[i].a[j][nw]; if((nw&3)==0) ++init_mat[i].a[j][nw|3]; if((nw&6)==0) ++init_mat[i].a[j][nw|6]; } } } int opt,x,y; ull ans=0; build(1,1,n); For(i,1,m){ opt=read(),x=read(),y=read(); if(opt==1) a[y]^=(1<<(x-1)),update(1,y); else{ Res=Matrix(1,8); Res.a[0][7]=1; query(1,x,y); ans=0; For(j,0,7) ans+=Res.a[0][j]; printf("%d\n",ans%p); } } return 0; } -
- 1
信息
- ID
- 10995
- 时间
- 4000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者