zoukankan      html  css  js  c++  java
  • [矩阵乘法][线段树][dp] Hdu P6155 Subsequence Count

     题解

    • 首先我们考虑dp,设f[i][0/1]为做到si,以0或1结尾的方案数
    • f[i][0]=f[i-1][0]+f[i-1][1]+1,f[i][1]=f[i-1][1] (当si==0时)
    • f[i][1]=f[i-1][0]+f[i-1][1]+1,f[i][0]=f[i-1][0] (当si==1时)
    • 考虑将其变成类似矩阵乘法的东东
    • 然后搞不考虑区间反转的话就可以取得40分的好成绩
    • 可以用线段树来维护矩阵乘法,那么现在考虑区间取反操作怎么搞
    • 当一个区间内的01串翻转之后相当于区间的矩阵第一行变为第二行,第一列变为第二列

    代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #define ll long long 
     4 using namespace std;
     5 const ll N=1e5+10,mo=1e9+7;
     6 int T,n,q,tag[N*4];
     7 char s[N];
     8 struct matrix
     9 {
    10     ll a[2][2];
    11     void init(int d) 
    12     { 
    13         if  (d>0) a[0][0]=a[0][1]=a[1][1]=1,a[1][0]=0; else  a[0][0]=a[1][0]=a[1][1]=1,a[0][1]=0; 
    14     }
    15     void change() { swap(a[0][0],a[1][1]),swap(a[0][1],a[1][0]); }
    16     matrix operator *(const matrix &b) const
    17     {
    18         matrix c;
    19         for (int i=0;i<2;i++) for (int j=0;j<2;j++) 
    20         {
    21             c.a[i][j]=0;
    22             for (int k=0;k<2;k++) c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j])%mo;
    23         }
    24         return c;
    25     }
    26 }mul[N*4],ans;
    27 void pushdown(int d) { if (tag[d]) tag[d*2]^=1,tag[d*2+1]^=1,mul[d*2].change(),mul[d*2+1].change(),tag[d]=0; }
    28 void build(int d,int l,int r)
    29 {
    30     tag[d]=0;
    31     if (l==r) { mul[d].init(s[l]-'0'); return; }
    32     int mid=l+r>>1;
    33     build(d*2,l,mid),build(d*2+1,mid+1,r),mul[d]=mul[d*2]*mul[d*2+1];
    34 }
    35 void change(int d,int l,int r,int L,int R)
    36 {
    37     if (L<=l&&r<=R) { tag[d]^=1,mul[d].change(); return; }
    38     pushdown(d); int mid=l+r>>1;
    39     if (L<=mid) change(d*2,l,mid,L,R);
    40     if (mid<R) change(d*2+1,mid+1,r,L,R);
    41     mul[d]=mul[d*2]*mul[d*2+1];
    42 }
    43 matrix query(int d,int l,int r,int L,int R)
    44 {
    45     if (L<=l&&r<=R) return mul[d];
    46     int mid=l+r>>1; matrix res; pushdown(d);
    47     res.a[0][0]=res.a[1][1]=1,res.a[0][1]=res.a[1][0]=0;
    48     if (L<=mid) res=res*query(d*2,l,mid,L,R);
    49     if (mid<R) res=res*query(d*2+1,mid+1,r,L,R);
    50     return res;
    51 }
    52 int main()
    53 {
    54     for (scanf("%d",&T);T;T--)
    55     { 
    56         scanf("%d%d%s",&n,&q,s+1),build(1,1,n);
    57         for (int op,l,r;q;q--)
    58         {
    59             scanf("%d%d%d",&op,&l,&r);
    60             if (op==2) ans=query(1,1,n,l,r),printf("%lld
    ",(ans.a[0][0]+ans.a[0][1]+ans.a[1][0]+ans.a[1][1]-2ll+mo)%mo); else change(1,1,n,l,r);
    61         } 
    62     } 
    63 }
  • 相关阅读:
    Django 数据库常用字段类型、选项参数、外键约束
    Django 项目基础配置
    MySQL连接列值
    SQL 限制查询结果
    python+appium+真机测试
    P3089 [USACO13NOV]POGO的牛Pogo-Cow
    P2889 [USACO07NOV]挤奶的时间Milking Time
    P2679 子串
    P3932 浮游大陆的68号岛
    P1514 引水入城
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11364351.html
Copyright © 2011-2022 走看看