[ARC119F]AtCoder Express 3

Posted Tan_tan_tann

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ARC119F]AtCoder Express 3相关的知识,希望对你有一定的参考价值。

AtCoder Express 3

题解

求从 0 0 0 n n n号点的方案数,我们应该很容易想到 d p dp dp
由于答案求的是最短路不超过 k k k的方案数,所以我们很容易想到将最短路加入状态中。
我们令 d p i , j , k , 0 / 1 dp_{i,j,k,0/1} dpi,j,k,0/1表示到点 i i i左边的第一个 A A A站台最短路为 j j j,到左边第一个 B B B最短路为 k k k,点 i i i A / B A/B A/B的方案数。
但很明显,如果直接这样 d p dp dp一定是会超时的,光是找左边的第一个 A / B A/B A/B站台都会很困难。

我们考虑左边第一个站台 A A A与左边第一个站台 B B B有什么关系。
很明显,我们可以从左边第一个站台 A A A跳过 i i i,再往回跳一位到 B B B
但这样的 B B B不一定在 i i i的左侧,但这并没有关系,我们可以将我们的 d p dp dp改一改, j , k j,k j,k表示到左边第一个 A / B A/B A/B站台及其右边的 A / B A/B A/B站台的最短路。
这样我们就可以将转移做到 O ( 1 ) O(1) O(1)了。

此外我们还发现了一个性质, ∣ j − k ∣ ⩽ 2 \\left|j-k\\right|\\leqslant 2 jk2
一旦超过了 2 2 2,我们就可以用上面的办法去使得它的最短路变得更小。
所以我们就没必要将 j , k j,k j,k全部记录下来了,我们就记录 j , Δ j,\\Delta j,Δ,使得 k = j + Δ k=j+\\Delta k=j+Δ
这样, d p dp dp的时间复杂度就是 O ( n k ) O\\left(nk\\right) O(nk)了。
容易得到转移方程式,
d p i , j , min ⁡ ( d + 1 , 2 ) , 0 + = d p i − 1 , j , d , 0 dp_{i,j,\\min(d+1,2),0}+=dp_{i-1,j,d,0} dpi,j,min(d+1,2),0+=dpi1,j,d,0
d p i , j , min ⁡ ( d + 1 , 1 ) , 0 + = d p i − 1 , j , d , 1 dp_{i,j,\\min(d+1,1),0}+=dp_{i-1,j,d,1} dpi,j,min(d+1,1),0+=dpi1,j,d,1
d p i , j + min ⁡ ( d − 1 , − 1 ) , max ⁡ ( d − 1 , − 1 ) , 1 + = d p i − 1 , j , d , 0 dp_{i,j+\\min(d-1,-1),\\max(d-1,-1),1}+=dp_{i-1,j,d,0} dpi,j+min(d1,1),max(d1,1),1+=dpi1,j,d,0
d p i , j + min ⁡ ( d , 1 ) , max ⁡ ( d − 1 , − 2 ) , 1 + = d p i − 1 , j , d , 1 dp_{i,j+\\min(d,1),\\max(d-1,-2),1}+=dp_{i-1,j,d,1} dpi,j+min(d,1),max(d1,2),1+=dpi1,j,d,1
跑一遍 d p dp dp即可。

时间复杂度 O ( n k ) O\\left(nk\\right) O(nk)

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 4005
#define lowbit(x) (x&-x)
#define reg register
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x7f7f7f7f;
const LL jzm=2333;
const int zero=2;
const int mo=1e9+7;
const double Pi=acos(-1.0);
typedef pair<int,int> pii;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int n,k,typ[MAXN],dp[2][MAXN][5][2],ans;
char str[MAXN];
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
void Add(int &x,int y){x=add(x,y);}
signed main(){
	read(n);read(k);scanf("%s",str+1);n--;
	for(int i=1;i<=n;i++)if(str[i]=='A')typ[i]=1;else if(str[i]=='B')typ[i]=2;
	if(typ[1]^1)dp[1][0][3][0]=1;if(typ[1]^2)dp[1][1][1][1]=1;
	for(int i=2;i<=n;i++){
		int now=i&1,las=now^1;
		for(int j=0;j<k+2;j++)
			for(int d=-2;d<=2;d++){
				if(typ[i]^1){
					if(dp[las][j][d+2][0])Add(dp[now][j][min(d+3,4)][0],dp[las][j][d+2][0]);
					if(dp[las][j][d+2][1])Add(dp[now][j][min(d+3,3)][0],dp[las][j][d+2][1]);
				}
				if(typ[i]^2){
					if(dp[las][j][d+2][0])Add(dp[now][j+min(d+1,1)][max(d+1,1)][1],dp[las][j][d+2][0]);
					if(dp[las][j][d+2][1])Add(dp[now][j+min(d+2,1)][max(d+1,0)][1],dp[las][j][d+2][1]);
				}
			}
		for(int j=0;j<k+2;j++)
			for(int d=-2;d<=2;d++)
				dp[las][j][d+2][0]=dp[las][j][d+2]<

以上是关于[ARC119F]AtCoder Express 3的主要内容,如果未能解决你的问题,请参考以下文章

Atcoder ARC101 E 树dp

AtCoder ARC 076E - Connected?

AtCoder ARC 076D - Built?

AtCoder ARC 082E - ConvexScore

Atcoder arc085

Atcoder arc077 D - 11 组合