1 条题解

  • 0
    @ 2026-5-8 20:31:39

    不妨先考虑一个朴素的 dp。记 fi,Sf_{i,S} 表示已经考虑到第 ii 列,并且格子可以使用情况为 SS(认为 00 是可以使用),aia_i 表示第 ii 行可以摆放的情况。

    考虑 fi1,Tf_{i-1,T} 对第 ii 行的状态可以有哪些贡献:

    • 摆放横着的瓷砖:如果放在第 jj 行,则要求 TTaia_i 的第 jj 个二进制位上都是 00;注意,可以不止放一个横着的瓷砖,也可以不仅放横着的瓷砖。

    • 摆放竖着的瓷砖:如果放在第 j,j+1j,j+1 行,则要求 aia_i 的第 j,j+1j,j+1 个二进制位上都是 00

    那么考虑枚举在哪些行放横着的瓷砖 SS',如果合法(即 SS'aia_iTT 无交),就进行转移;在此基础上,判断能否放竖着的瓷砖,如果可以就转移。

    初始状态为 f0,71f_{0,7}\leftarrow 1,因为在第一列不能利用上一列的空位。

    上面的时间复杂度为 O(nqS)O(nqS),其中 SS 是状态数,为 88。常数良好可以轻松通过第 1,31,3 个子任务。

    考虑第二个子任务。因为只有一种状态,那么无论询问区间是什么,答案之和区间长度有关,因此可以预处理每一个区间长度的答案。

    因为转移是固定的,且状态数较少,所以考虑 ddp。预处理每一个 aia_i 的取值对于的转移矩阵,然后用线段树进行询问和修改,时间复杂度为 O((n+q)lognS3)O((n+q)\log nS^3)

    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
    上传者