E - RLE Editorial by Y_CN_3_dot_42H2O


First, let’s consider a string with the same alphabet \(S\), the new string is \(T\):

  • \(|S|<10\), then \(|T|=2\).
  • \(|S|<100\), then \(|T|=3\).
  • \(|S|<1000\), then \(|T|=4\).
  • \(|S|<10000\), then \(|T|=5\).

So, a function can be defined as this: \( g(x)=\begin{cases} 2&(1\le x<10)\\ 3&(10\le x<100)\\ 4&(100\le x<1000)\\ 5&(1000\le x<10000)\end{cases} \)

Then, the problem can be solved with Dynamic Programming (DP).

The definition of DP

\(f[i][j]:=\) the number of strings that the original length is \(i\) and the new length is \(j\).

Since the \(i,j\) are in the range \([1,n]\), so there are \(O(N^2)\) states.

The initial value of DP

First of all, let \(f[i][g(i)]=26\) and fill the remaining elements with \(0\).

The transition of DP

Compute in the increasing order of \(i\). For \(j=1,2,...,n\) and \(k=1,2,...,n-i\).

  • if \(j+g(k)\le n\), add \(25\times f[i][j]\) to \(f[i+k][j+g(k)]\), since the adjacent alphabets are different.

Answer

Finally, the answer is \(\sum_{j<i<n} f[i][j]\).

Now the computational complexity is \(O(N^3)\), which is not enough to pass this problem.

The optimization of DP

We can find that the \(g(k)\) is in \([2,3,4,5]\), so we can use fenwick tree to optimize it.

There are \(n\) fenwick trees, the \(i\)-th is called \(C[i]\).

For each \(i,j\):

  • Add \(25\times f[i][j]\) to the \((i+1)\)-th element of \(C[j+2]\), and subtract it to the \((i+10)\)-th element of \(C[j+2]\).
  • Add \(25\times f[i][j]\) to the \((i+10)\)-th element of \(C[j+3]\), and subtract it to the \((i+100)\)-th element of \(C[j+3]\).
  • Add \(25\times f[i][j]\) to the \((i+100)\)-th element of \(C[j+4]\), and subtract it to the \((i+1000)\)-th element of \(C[j+4]\).
  • Add \(25\times f[i][j]\) to the \((i+1000)\)-th element of \(C[j+5]\).

Now the computational complexity is \(O(N^2\log N)\), which is enough to pass this problem.

Code:

#include<bits/stdc++.h>
#define ll long long
#define il inline
#define ret return
using namespace std;
bool smoke_alarm1;
const int N=3e3+7;
const int Pa=998244353;
il ll read(){
	char c;
	ll x=0,f=1;
	while(!isdigit(c=getchar())){
		if(c==EOF)
			return -1321321327;
		f-=(c=='-')<<1;
	}
	while(isdigit(c)){
		x=(x<<3)+(x<<1)+f*(c^48);
		c=getchar();
	}
	ret x;
}
il void write(ll x,char ch='\n'){
	if(x<0)
		putchar('-');
	static char r[55];
	int cnt=0;
	do{
		int y=x%10;
		y=abs(y);
		r[++cnt]=y|48;
		x/=10;
	}while(x);
	for(int i=cnt;i;--i)
		putchar(r[i]);
	if(ch)
		putchar(ch);
}
template<class T,class T2>il void add(T& x,T2 y,int p=Pa){
	x+=y;
	if(x>=p)
		x-=p;
}
ll n,p,res,f[N][N];
struct BIT{
	ll c[N];
	BIT(){
		memset(c,0,sizeof(c));
	}
	void Add(int x,ll k){
		++x;
		for(;x<=n+1;x+=x&-x)
			add(c[x],k,p);
	}
	ll Ask(int x){
		++x;
		ll k=0;
		for(;x;x-=x&-x)
			add(k,c[x],p);
		ret k;
	}
}g[N];
int main(){
	n=read();
	p=read();
	g[2].Add(1,26);
	g[2].Add(10,p-26);
	g[3].Add(10,26);
	g[3].Add(100,p-26);
	g[4].Add(100,26);
	g[4].Add(1000,p-26);
	g[5].Add(1000,26);
	for(int i=1;i<=n;++i)
	for(int j=1;j<=n;++j){
		f[i][j]=g[j].Ask(i);
		if(!f[i][j])
			continue;
		g[j+2].Add(i+1,25*f[i][j]%p);
		g[j+2].Add(i+10,p-25*f[i][j]%p);
		g[j+3].Add(i+10,25*f[i][j]%p);
		g[j+3].Add(i+100,p-25*f[i][j]%p);
		g[j+4].Add(i+100,25*f[i][j]%p);
		g[j+4].Add(i+1000,p-25*f[i][j]%p);
		g[j+5].Add(i+1000,25*f[i][j]%p);
	}
	for(int i=1;i<n;++i)
		add(res,f[n][i],p);
	write(res);
	ret 0;
}

Since my English is poor, there may be some gramma mistakes.

posted:
last update: