AT_abc232_e [ABC232E] Rook Path
题意
已经够清晰了。
思路
由于直接转移复杂度太高,考虑另类转移。
设 \(f_{i,j}\) 表示移动了 \(i\) 步之后,状态为 \(j\):
- 当 \(j\) 为 \(0\) 时,表示在原点上;
- 当 \(j\) 为 \(1\) 时,表示在原点那一行上,但不在原点上;
- 当 \(j\) 为 \(2\) 时,表示在原点那一列上,但不在原点上;
- 当 \(j\) 为 \(3\) 时,表示既不在原点那一行上,也不在原点那一行上。
于是得到转移:
- \(f{i,0}=f_{i-1,1}\times (W-1)+f_{i-1,2}\times (H-1)\);
- \(f{i,1}=f{i,0}+f_{i-1,1}\times (W-2)+f_{i-1,3}\times (H-1)\);
- \(f{i,2}=f{i,0}+f_{i-1,2}\times (W-2)+f_{i-1,3}\times (H-1)\);
- \(f{i,3}=f_{i-1,1}+f_{i-1,2}+f_{i-1,3}\times(W+H)\);
可以发现第一维是可以压掉的,我就用临时变量代替了。
code
//By _maple_leaf_
#include<bits/stdc++.h>
#define FAST true
#define FIO true
#define DEBUG true
using namespace std;
#if FIO
void fio(string s,int i=0){
freopen(((s+(i?to_string(i):""))+".in").c_str(),"r",stdin);
freopen(((s+(i?to_string(i):""))+".out").c_str(),"w",stdout);
}
#endif
#define int long long
#define _27 998244353
//#define int unsigned int
//#define int __int128
#if DEBUG
bool Memory_start;
void debug();
#endif
#if FAST
inline int read(){
char c=getchar();
int ret=0,f=1;
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
ret=(ret<<3)+(ret<<1)+c-'0';
c=getchar();
}return ret*f;
}
inline void write(int x,int op=0){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10,0);
putchar((char)(x%10+'0'));
if(op){
if(op>0)puts("");
if(op<0)putchar(' ');
if(op==0)puts("114514");
}
}
#endif
int h,w,k;
int x,y,X,Y;
int Ta,chi,ba,na;
signed main(){
h=read(),w=read(),k=read(),x=read(),y=read(),X=read(),Y=read();
Ta=1;
for(int i=1;i<=k;i++){
int ta,tb,tc,td;
(ta=chi*(w-1)+ba*(h-1))%=_27;
(tb=Ta+chi*(w-2)+na*(h-1))%=_27;
(tc=Ta+ba*(h-2)+na*(w-1))%=_27;
(td=chi+ba+na*(w+h-4))%=_27;
Ta=ta,chi=tb,ba=tc,na=td;
}
if(x==X&&y==Y)write(Ta);
else if(x==X&&y!=Y)write(chi);
else if(x!=X&&y==Y)write(ba);
else write(na);
#if DEBUG
debug();
#endif
return 0;
}//~*完结撒花*~
#if DEBUG
bool Memory_end;
void debug(){
cerr<<"Time: "<<clock()<<" ms\n";
cerr<<fixed<<setprecision(6)<<"Memory: "<<abs(&Memory_start-&Memory_end)/1024.0/1024.0<<" MB";
}
#endif

浙公网安备 33010602011771号