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
浙公网安备 33010602011771号