250602 模拟赛

分数:\(19+40+40=99\)

先看题,看完 T1 本来就开始想了,但是又去把后面的题都看了一下。然后 T2 一眼会了暴力,T3 看懂之后一眼会了暴力,然后加上这俩题的性质分想想写写调调就十二点了。然后开始写 T1,打打表发现情况不是很多于是开始爆搜,试图想了一下性质但是没想出来。


T1 移除石子2

有一个长度为 \(n\) 的序列 \(a\),每次可以选择 \(2\le i\le n-1\),将 \(a_i\) 减一,\(a_{i-1}\)\(a_{i+1}\) 加一,如果这个序列是否能达到每一项都是 \(2\) ,则为合法序列。给定 \(m\)\(a_{x_i}=y_i\) 的限制,问存在多少合法序列。

注意到一个合法的序列可以分成若干个合法子串,每一段形如:

  • \(2\)
  • \(1,3,1\)
  • \(1,1,2,1,1\)
  • \(1,2,...(若干个 1),2,1\)

发现状态比较的少考虑矩阵乘法加速转移。时间复杂度能过。(我画的图非常好但是在演草纸)

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline ll read()
{
	ll t=0;char h=getchar();
	while(!isdigit(h))h=getchar();
	while(isdigit(h))t=(t<<1)+(t<<3)+(h^48),h=getchar();
	return t;
}
void write(int x)
{
	if(x>9)write(x/10);putchar(x%10+'0');
}
const int mod=1e9+7;
const int N=10;
struct mtx{
	ll t[N][N];int n,m;
}a[5],b[70],now;
inline mtx operator+(mtx a,mtx b)
{
	for(int i=1;i<=a.n;i++)
		for(int j=1;j<=a.m;j++)(a.t[i][j]+=b.t[i][j])%=mod;
	return a;
}
inline mtx operator*(mtx a,mtx b)
{
	mtx c;memset(c.t,0,sizeof c.t);c.n=a.n;c.m=b.m;
	for(int i=1;i<=a.n;i++)
		for(int j=1;j<=b.m;j++)
			for(int k=1;k<=a.m;k++)
				(c.t[i][j]+=a.t[i][k]*b.t[k][j]%mod)%=mod;
	return c;
}
inline void quikp(mtx&a,ll n)
{
	for(int i=0;n;n>>=1,++i)if(n&1)a=a*b[i];
}
inline void print(mtx a)
{
	for(int i=1;i<=a.n;i++)
	{
		for(int j=1;j<=a.m;j++)cout<<a.t[i][j]<<" ";puts("");
	}puts("");
}
ll las=0,x,y,n,m;
int main()
{
	for(int i=1;i<=3;i++)a[i].n=a[i].m=6;now.n=1;now.m=6;now.t[1][6]=1;
	a[1].t[6][1]=a[1].t[1][2]=a[1].t[3][4]=a[1].t[5][5]=a[1].t[4][6]=1;
	a[2].t[6][6]=a[2].t[1][5]=a[2].t[2][3]=a[2].t[5][4]=1;
	a[3].t[1][4]=1;
	b[0]=a[1]+a[2]+a[3];
	for(int i=1;i<=64;i++)b[i]=b[i-1]*b[i-1];
	n=read();m=read();
	while(m--)
	{
		x=read();y=read();
		if(y>3)
		{
			write(0);return 0;
		}
		quikp(now,x-las-1);now=now*a[y];las=x;
	}
	quikp(now,n-las);write(now.t[1][6]);
	return 0;
}

T2 音符大师2

突然发现没看过性质 D 怎么会是。

\(n\) 个音符从天上掉下来,你需要移动线段接住它们,求移动的总距离之和。\(q\) 次询问。

观察性质 D 发现每次都需要移动线段,可以最开始的部分特判后面的部分 \(O(n)\) 预处理,计算答案是 \(O(1)\) 的。

注意到连续的 \(3\) 个或者以上相同移动方向的 \(p\) 可以删掉中间的,当作只有两个来考虑。对于一条线段来说,如果有一个 \(i\) 使得 \(|p_i-p_{i-1}|\) 是最小的,那么发现在从 \(p_{i-1}\)\(p_{i+2}\) 的移动过程中,如果 \(len\ge |p_i-p_{i-1}|\),就可以把中间两个点删掉。重复这样做直到满足性质 \(D\) 的话就可以 \(O(1)\) 计算。

gugugu


T3 树上邻域数点2

一棵树,每次询问把到距离 \(x_i\le y_i\) 的点的信息合并,并且修改。

gugugugu

posted @ 2025-06-03 16:55  baiguifan  阅读(41)  评论(0)    收藏  举报