首页 > 其他分享 >洛谷 P7739 - [NOI2021] 密码箱

洛谷 P7739 - [NOI2021] 密码箱

时间:2023-08-11 22:24:46浏览次数:46  
标签:begin P7739 end mat 密码箱 times NOI2021 bmatrix 序列

感觉难度和今年 D2T2 差不多。

首先一个很显然的事情是,每一步得到的分数的分子分母都是互质的,证明参考 SBT。而最后答案要求我们将分子分母都求出来而不是求分数值,所以可以很明显的想到将分数当成一个二元组然后维护变换。

考虑从右往左扫,假设当前分数为 \(\dfrac{x}{y}\),那么扫过 \(a_k\) 这个元素之后就会变成,\(\begin{bmatrix}x&y\end{bmatrix}\times\begin{bmatrix}a_{k}&1\\1&0\end{bmatrix}\),而初始情况为了满足 \(\begin{bmatrix}x&y\end{bmatrix}\times\begin{bmatrix}a_{k}&1\\1&0\end{bmatrix}=\begin{bmatrix}a_k&1\end{bmatrix}\),所以初始情况应有 \(x=1,y=0\),所以如果给的是序列 A 而不是 WE 序列,那么所求即为 \(\begin{bmatrix}a_{k}&1\\1&0\end{bmatrix}\begin{bmatrix}a_{k-1}&1\\1&0\end{bmatrix}\cdots\begin{bmatrix}a_{1}&1\\1&0\end{bmatrix}\),使用线段树维护矩阵乘法即可。

接下来考虑怎么维护这个 WE 序列。先考虑 W,由于 \(\begin{bmatrix}1&1\\0&1\end{bmatrix}\begin{bmatrix}a_{k}&1\\1&0\end{bmatrix}=\begin{bmatrix}a_{k}+1&1\\1&0\end{bmatrix}\),所以如果序列末尾有个 W,那么相当于在整个矩乘的式子左边添加一个 \(\begin{bmatrix}1&1\\0&1\end{bmatrix}\)。

其次考虑 E。考虑 E 的两种情况:

  • 序列的最后一个元素为 \(1\),由于 \(\begin{bmatrix}x&y\end{bmatrix}\times\begin{bmatrix}1&1\\1&0\end{bmatrix}\times \begin{bmatrix}1&1\\0&1\end{bmatrix}=\begin{bmatrix}x+y&2x+y\end{bmatrix}\),且 \(\begin{bmatrix}x&y\end{bmatrix}\times\begin{bmatrix}2&-1\\1&0\end{bmatrix}\times\begin{bmatrix}1&1\\1&0\end{bmatrix}=\begin{bmatrix}x+y&2x+y\end{bmatrix}\),所以这种情况相当于在序列左边添加一个 \(\begin{bmatrix}2&-1\\1&0\end{bmatrix}\)。
  • 序列的最后一个元素不是 \(1\),那么相当于在序列左边添加 \(\begin{bmatrix}1&1\\1&0\end{bmatrix}\times \begin{bmatrix}1&1\\1&0\end{bmatrix}\times \begin{bmatrix}-1&1\\1&0\end{bmatrix}\),而我们刚好发现这个式子的结果也是 \(\begin{bmatrix}2&-1\\1&0\end{bmatrix}\)。

换句话说,如果序列末尾有个 E,那么相当于在整个矩乘的式子左边添加一个 \(\begin{bmatrix}2&-1\\1&0\end{bmatrix}\)。

这样问题就容易了:相当于把序列 reverse 过来,把 w 替换为 \(\begin{bmatrix}1&1\\0&1\end{bmatrix}\),E 替换为 \(\begin{bmatrix}2&-1\\1&0\end{bmatrix}\),求矩阵连乘后的结果。由于涉及 reverseflip,使用平衡树维护即可。

const int MAXN=2e5;
const int MOD=998244353;
mt19937 rng(time(0));
int n,qu;char str[MAXN+5];
struct mat{
	int a[2][2];
	mat(){memset(a,0,sizeof(a));}
	friend mat operator *(const mat &X,const mat &Y){
		mat res;
		for(int i=0;i<2;i++)for(int j=0;j<2;j++)for(int k=0;k<2;k++)
			res.a[i][j]=(res.a[i][j]+1ll*X.a[i][k]*Y.a[k][j])%MOD;
		return res;
	}
}W,E,I;
struct node{int ch[2],key,typ,siz,rev_lz,flip_lz;mat v[2][2];}s[MAXN+5];
int rt,ncnt;
int nwnd(int x){
	++ncnt;s[ncnt].key=rng();s[ncnt].typ=x;s[ncnt].siz=1;
	s[ncnt].v[0][0]=s[ncnt].v[0][1]=(x)?E:W;
	s[ncnt].v[1][0]=s[ncnt].v[1][1]=(x)?W:E;
	return ncnt;
}
void pushup(int k){
	s[k].v[0][0]=s[s[k].ch[0]].v[0][0]*((s[k].typ)?E:W)*s[s[k].ch[1]].v[0][0];
	s[k].v[1][0]=s[s[k].ch[0]].v[1][0]*((s[k].typ)?W:E)*s[s[k].ch[1]].v[1][0];
	s[k].v[0][1]=s[s[k].ch[1]].v[0][1]*((s[k].typ)?E:W)*s[s[k].ch[0]].v[0][1];
	s[k].v[1][1]=s[s[k].ch[1]].v[1][1]*((s[k].typ)?W:E)*s[s[k].ch[0]].v[1][1];
	s[k].siz=s[s[k].ch[0]].siz+s[s[k].ch[1]].siz+1;
}
void tag_rev(int k){
	swap(s[k].ch[0],s[k].ch[1]);s[k].rev_lz^=1;
	swap(s[k].v[0][0],s[k].v[0][1]);swap(s[k].v[1][0],s[k].v[1][1]);
}
void tag_flip(int k){
	s[k].typ^=1;s[k].flip_lz^=1;
	swap(s[k].v[0][0],s[k].v[1][0]);swap(s[k].v[0][1],s[k].v[1][1]);
}
void pushdown(int k){
	if(s[k].rev_lz){
		if(s[k].ch[0])tag_rev(s[k].ch[0]);
		if(s[k].ch[1])tag_rev(s[k].ch[1]);
		s[k].rev_lz=0;
	}
	if(s[k].flip_lz){
		if(s[k].ch[0])tag_flip(s[k].ch[0]);
		if(s[k].ch[1])tag_flip(s[k].ch[1]);
		s[k].flip_lz=0;
	}
}
int merge(int a,int b){
	if(!a||!b)return a+b;pushdown(a);pushdown(b);
	if(s[a].key<s[b].key)return s[a].ch[1]=merge(s[a].ch[1],b),pushup(a),a;
	else return s[b].ch[0]=merge(a,s[b].ch[0]),pushup(b),b;
}
void split(int k,int sz,int &a,int &b){
	if(!k)return a=b=0,void();pushdown(k);
	if(sz<=s[s[k].ch[0]].siz)return b=k,split(s[k].ch[0],sz,a,s[k].ch[0]),pushup(k),void();
	else return a=k,split(s[k].ch[1],sz-s[s[k].ch[0]].siz-1,s[k].ch[1],b),pushup(k),void();
}
void calc(){
	int x=s[rt].v[0][0].a[0][0],y=s[rt].v[0][0].a[0][1];
	printf("%d %d\n",x,(x+y)%MOD);
}
int main(){
	scanf("%d%d%s",&n,&qu,str+1);
	W.a[0][0]=1;W.a[0][1]=1;W.a[1][0]=0;W.a[1][1]=1;
	E.a[0][0]=2;E.a[0][1]=MOD-1;E.a[1][0]=1;E.a[1][1]=0;
	I.a[0][0]=I.a[1][1]=1;
	for(int i=0;i<2;i++)for(int j=0;j<2;j++)s[0].v[i][j]=I;
	for(int i=1;i<=n;i++)rt=merge(nwnd(str[i]=='E'),rt);
	calc();
	while(qu--){
		static char opt[10];scanf("%s",opt+1);
		if(opt[1]=='A'){
			static char chr[10];scanf("%s",chr+1);
			++n;rt=merge(nwnd(chr[1]=='E'),rt);
		}else if(opt[1]=='F'){
			int l,r,k1,k2,k3;scanf("%d%d",&l,&r);
			swap(l,r);l=n-l+1;r=n-r+1;
			split(rt,r,k1,k3);split(k1,l-1,k1,k2);tag_flip(k2);
			rt=merge(merge(k1,k2),k3);
		}else{
			int l,r,k1,k2,k3;scanf("%d%d",&l,&r);
			swap(l,r);l=n-l+1;r=n-r+1;
			split(rt,r,k1,k3);split(k1,l-1,k1,k2);tag_rev(k2);
			rt=merge(merge(k1,k2),k3);
		}calc();
	}
	return 0;
}
/*
10 1
EEWEEWWWEE
FLIP 1 9
*/

标签:begin,P7739,end,mat,密码箱,times,NOI2021,bmatrix,序列
From: https://www.cnblogs.com/tzcwk/p/luogu-P7739.html

相关文章

  • [NOI2021] 路径交点 题解
    [NOI2021]路径交点题解题意给定一张\(k\)层的有向图,第\(i\)层有\(n_i\)​个顶点,第​\(1\)层与第\(k\)​层顶点数相同。对于第​​\(j\)\((1\leqj<k)\)层的顶点,只会连向第\(j+1\)层的顶点。没有边连向第\(1\)层的顶点,第\(k\)层的顶点不会向其他顶点连边......
  • NOI2021 题解
    [NOI2021]轻重边转化一下题意:每次给一条链染色,查一条链从\(x\)到\(y\)有几条边两端颜色相同。那这个随便树剖线段树就好了。也可以LCT,码量可能要小点。#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>usingnamespace......
  • 「NOI2021」庆典
    首先可以注意到题面中的这个条件:对于三座城市\(x\),\(y\),\(z\),若\(x\Rightarrowz\)且\(y\Rightarrowz\),那么有\(x\Rightarrowy\)或\(y\Rightarrowx\)。这就代表着如果存在边\(x\rightarrowz\)和\(y\rightarrowz\),假设存在\(x\Rightarrowy\)那么删去边\(x\r......
  • luogu P7740 [NOI2021] 机器人游戏
    题面传送门一个bitset值52分?首先样例让你容斥你就容斥,枚举哪些位是可以的,计算每一位的\(p_0,p_1,q_0,q_1\)表示是否被要求最后是\(0/1\),是否有最终值是开始值异或\(0/1\)。然后每个位置的贡献可以分类讨论出来:如果\(p_0,p_1\)或者\(q_0,q_1\)都有,那只能空着。如......
  • [P7738][NOI2021] 量子通信
    [NOI2021]量子通信题目背景由于评测性能差异,本题时限+0.5s。题目描述小Z正在自学量子计算机相关知识,最近他在研究量子通信章节,并遇到了一个有趣的问题。在该问题中,Alice和Bob正在进行量子通信,它们的通信语言是一个大小为\(n\)的字典\(S\),在该字典中,每一个单词\(s_i......
  • 「NOI2021」机器人游戏
    链接:https://www.luogu.com.cn/problem/P7740题目描述:有\(m\)个机器人和\(m\)张纸袋,每个纸袋有\(n\)个格子,每个格子可能是空,写有数字\(0\)或写有数字\(1\)。每......
  • P7737 [NOI2021] 庆典
    题意给定一张有向图,每次询问给出\(s,t\),求从\(s\tot\)的路径上(可以有重复点)可能会经过多少个点,每次询问会临时加入\(k\)条边。其中,题目给出的图有如下特点:若\(x\)......
  • NOI2021模拟测试赛(六十)
    题面西克把\(x\toy\)拆成\(x\tolca\toy\),而\(x\tolca\)的部分很好搞,不予阐述。关键是\(y\tolca\)的部分,我们考虑离线解决。从上往下走时,对每种颜色\(c\)......