题解:CF2091F Igor and Mountain
Magallan_forever · · 题解
简要说明题意:
给出一张 X 的位置可走。要求从第
- 每层都必须经过且每层的节点只能经过至多两个。
- 如果当前处于
k 层,下一次移动后只能处于k 层或k-1 层。 - 一次移动的欧式距离
x \leq d 。
求路径方案数,对
题目分析:
对于点
令
看着可能很抽象,其实就是先更新从下层走到本层,再更新本层相互走的情况。
初状态是所有第
区间求和我用了树状数组,但其实前缀和足够了;D。时间复杂度是 WA*2。
代码如下:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
const int mod=998244353;
int m;
bool map_[2001][2001];
long long c[2001][2001],f[2001][2001];//这里的c,f都可以滚成两个数组,即当前层和上一层
int lowbit(int v){
return v&(-v);
}
void modify(long long* c,int x,long long v){
for(;x<=m;x+=lowbit(x)) (c[x]+=v)%=mod;
}
long long query(long long* c,int l,int r){ //[l,r]
long long cnt=0ll;
for(;r;r-=lowbit(r)) cnt+=c[r],cnt%=mod;
for(--l;l;l-=lowbit(l)) cnt-=c[l],(cnt+=mod)%=mod;
return cnt%mod;
}
string s;
int main(){
int T,n,d;
long long cnt,temp;
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&d);
for(int i=1;i<=n;++i){
cin>>s,fill(c[i]+1,c[i]+1+m,0ll),fill(f[i]+1,f[i]+1+m,0ll);
for(int j=0;j<m;++j) map_[i][j+1]=(s[j]=='X');
}
for(int i=1;i<=m;++i) f[n][i]=map_[n][i],modify(c[n],i,map_[n][i]);
for(int i=1;i<=m;++i) if(map_[n][i]) f[n][i]=query(c[n],max(1,i-d),min(m,i+d))%mod;
for(int i=1;i<=m;++i)
if(map_[n][i]){
temp=f[n][i]%mod-query(c[n],i,i),(temp+=mod)%=mod;
modify(c[n],i,temp);
}
for(int i=n-1;i;--i){
for(int j=1;j<=m;++j)
if(map_[i][j]){
f[i][j]=query(c[i+1],max(1,j-d+1),min(m,j+d-1));
// printf("i=%d j=%d f[i][j]=%lld\n",i,j,f[i][j]);
}
for(int j=1;j<=m;++j)
if(map_[i][j]){
temp=f[i][j]-query(c[i],j,j),(temp+=mod)%=mod;
modify(c[i],j,temp);
}
for(int j=1;j<=m;++j) if(map_[i][j]) f[i][j]=query(c[i],max(1,j-d),min(m,j+d));
for(int j=1;j<=m;++j)
if(map_[i][j]){
temp=f[i][j]-query(c[i],j,j),(temp+=mod)%mod;
modify(c[i],j,temp);
}
}
cnt=0ll;
for(int i=1;i<=m;++i) cnt+=f[1][i],cnt%=mod;
printf("%lld\n",cnt);
// for(int i=1;i<=n;putchar('\n'),++i) for(int j=1;j<=m;++j) printf("%lld ",f[i][j]);
}
return 0;
}