题目链接:序列
题意:
一开始有一个长度为n的全0串,m次操作,每次操作:第i次操作,先将原来的每一个串复制成两个相同的串,再把相同的两个中的一个l,r区间修改为i。对于一个串含有「极大连续段」即为区间[l,r]相同。求解每次操作结束后所有串的所有「极大连续段」之和
解析:
定义一个函数
f
(
x
)
f(x)
f(x)表示含有以x(1<=x<=n)位置为「极大连续段」的结束点的串个数。
对于每一次的修改,(l,r):修改的串使
f
(
r
)
f(r)
f(r)受影响,
f
(
r
)
=
f
(
r
)
+
2
f(r)=f(r)+2
f(r)=f(r)+2i-1,也使
f
(
l
−
1
)
f(l-1)
f(l−1)受影响,
f
(
l
−
1
)
=
f
(
l
−
1
)
+
2
f(l-1)=f(l-1)+2
f(l−1)=f(l−1)+2i-1。 对于小于l-1和大于r的位置,只受复制的影响所有乘二。 对于(l,r)的位置,修改的串对这些位置的f值没有贡献,故f值还等于没复制时的值。
#include<bits/stdc++.h>
using namespace std;
const int mod=20050321;
long long t[2010],f[2010];
void List(){
t[0]=1;
for(int i=1;i<2010;++i){
t[i]=t[i-1]*2%mod;
}
}
int main(){
List();
memset(f,0,sizeof f);
int n,m,l,r;
scanf("%d%d",&n,&m);
f[n]=1;
for(int i=1;i<=m;++i){
scanf("%d%d",&l,&r);
for(int j=1;j<l-1;++j){
f[j]=f[j]*2%mod;
}
f[l-1]=(f[l-1]+t[i-1])%mod;
for(int j=r+1;j<=n;++j){
f[j]=f[j]*2%mod;
}
f[r]=(f[r]+t[i-1])%mod;
long long ans=0;
for(int i=1;i<=n;++i){
ans=(ans+f[i])%mod;
}
printf("%d\n",ans);
}
}