hdu 2068
#include
using namespace std;
//用线段树维护一个2*2的矩阵,a[i][j]表示从这一层第i个门到下一层第j个门是否联通,
//第i层到第j层之间的矩阵相乘之后的结果矩阵,各元素和为从第i层到第j层的种类数
const int mod=1000000007;
struct mat{
long long a[2][2];
}tr[400005];
mat mul(mat x,mat y)
{
mat ne;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
ne.a[i][j]=0;
for(int k=0;k<2;k++)
{
ne.a[i][j]=(ne.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
}
}
}
return ne;
}
void build(int i,int l,int r)
{
if(l==r)
{
for(int ii=0;ii<2;ii++)
{
for(int j=0;j<2;j++)
tr[i].a[ii][j]=1;
}
return ;
}
int mid=l+r>>1;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
tr[i]=mul(tr[i*2],tr[i*2+1]);
}
void update(int i,int l,int r,int x,int y,int z)
{
if(l==r)
{
tr[i].a[y][z]^=1;
return ;
}
int mid=l+r>>1;
if(x<=mid)
update(i*2,l,mid,x,y,z);
else
update(i*2+1,mid+1,r,x,y,z);
tr[i]=mul(tr[i*2],tr[i*2+1]);
}
mat query(int i,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
{
return tr[i];
}
int mid=l+r>>1;
mat ans;
for(int ii=0;ii<2;ii++)
{
for(int j=0;j<2;j++)
{
if(ii==j)
ans.a[ii][j]=1;
else
ans.a[ii][j]=0;
}
}
if(x<=mid)
ans=mul(ans,query(i*2,l,mid,x,y));
if(y>mid)
ans=mul(ans,query(i*2+1,mid+1,r,x,y));
return ans;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
build(1,1,n);
int op,x,y,z;
while(m--)
{
scanf("%d",&op);
if(op==0)
{
scanf("%d%d",&x,&y);
mat t=query(1,1,n,x,y-1);
long long ans=0;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
ans+=t.a[i][j],ans%=mod;
}
printf("%lld\n",ans);
}
else
{
scanf("%d%d%d",&x,&y,&z);
update(1,1,n,x,y-1,z-1);
}
}
}
return 0;
}
多校E
#include
using namespace std;
int n,m,q;
int b[50010][20];
const int mod=1000000007;
char s[30];
struct mat{
long long a[11][11];
friend mat operator *(const mat &a,const mat &b)//行与行之间的关系通过乘的形式进行转换
{
mat c;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=m;j++)
{
c.a[i][j]=0;
for(int k=1;k<=m;k++)
c.a[i][j]=(c.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
}
}
return c;
}
}tr[300040];//tr[1].a[i][j]表示所有行乘积后,从第b[1][i]到b[n][j]有多少可行路线
void work(int b[],mat &ans)//在这一行中ans.a[i][j]表示在在b这一行中是否能从i到j
{
memset(ans.a,0,sizeof(ans.a));
for(int i=1;i<=m;i++)
{
int j=i;
for(;j>=1&&!b[j];ans.a[i][j]=1,j--);
j=i;
for(;j<=m&&!b[j];ans.a[i][j]=1,j++);
}
}
void build(int i,int l,int r)
{
if(l==r)
{
work(b[l],tr[i]);
return ;
}
int mid=l+r>>1;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
tr[i]=tr[i*2]*tr[i*2+1];
}
void update(int i,int l,int r,int x)
{
if(l==r)
{
work(b[l],tr[i]);
return;
}
int mid=l+r>>1;
if(x<=mid)
update(i*2,l,mid,x);
else
update(i*2+1,mid+1,r,x);
tr[i]=tr[i*2]*tr[i*2+1];
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
for(int j=1;j<=m;j++)
b[i][j]=s[j]-'0';
}
build(1,1,n);
while(q--)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1)
{
b[x][y]^=1;
update(1,1,n,x);
}
else
printf("%lld\n",tr[1].a[x][y]);
}
return 0;
}