P4621 [COCI2012-2013#6] BAKTERIJE 题解
P4621 [COCI2012-2013#6] BAKTERIJE 题解
知识点
扩展中国剩余定理。
题意分析
给你 \(K\) 个网格图及其起点坐标和方向,求 \(K\) 个网格图上的点同时到达给定终点 \((X,Y)\) 的最小时间。
思路分析
首先,显而易见的是每个点得拆成四个方向的分点,而每个方向只有一个出边,这就容易让人想到内向基环树。但是,这题的起点是固定的,那么我们最多只需维护一条基环树下的链,所以一遍 DFS 或迭代就可以搞定链长和环长。
那么最后的求解我们需要分别枚举 \(K\) 个网格图到达给定终点 \((X,Y)\) 时的方向,也就是它所拆成的四个点,这可以二进制枚举、DFS 或格雷码实现。
现在再考虑处理细节。假设我们现在处理的终点 \((X,Y,D)\)(\(D\) 为其方向)是在以下情况:
-
终点 \((X,Y,D)\) 在环上:
设环长为 \(Cyc\),从起点第一次到终点 \((X,Y,D)\) 的时间为 \(Tim\),那么我们所求的答案 \(res\) 就需要满足 \(res \equiv Tim \pmod {Cyc} \land res \ge Tim\)。
-
终点 \((X,Y,D)\) 在链上:
那么这张图从起点到达终点 \((X,Y,D)\) 的时间 \(Tim\) 有且仅有一种,那么我们所求的答案 \(res\) 就需要满足 \(res =Tim\)。
那么最后的统计也很简单:
-
所有枚举到的终点都在各自图的环上:
那么题目就变成了一个线性同余方程组,注意到模数不一定互质,所以需要用扩展中国剩余定理。
-
有任意一个不在环上:
就简单的判断一下同余就好了。
由于本题范围可以超过 long long,所以需要 __int128(不过数据没超过 long long 的范围,也可以不开)。
注:本题细节很多,要谨慎编码。
CODE
时间复杂度:\(O(4^K K \log_2{A} + N M K)\)(\(A\) 为求解扩展中国剩余定理时的最大数值),空间复杂度:\(O(n^2)\)。
#include<bits/stdc++.h>
#define Fi first
#define Se second
#define ll long long
#define Pll pair<ll,ll>
#define INF 0x3f3f3f3f3f3f3f3f
#define tomax(a,b) ((a)=max((a),(b)))
#define tomin(a,b) ((a)=min((a),(b)))
#define FOR(i,a,b) for(int i=(a);i<=(int)(b);++i)
#define DOR(i,a,b) for(int i=(a);i>=(int)(b);--i)
#define RCL(a,b,c,d) memset((a),(b),sizeof(c)*(d))
#define main Main();signed main(){ios::sync_with_stdio(0);cin.tie(0);return Main();}signed Main
using namespace std;
typedef __int128 Int;
namespace IOstream{
#define getc() getchar()
#define putc(c) putchar(c)
#define blank(c) ((c)==' '||(c)=='\n'||(c)=='\r'||(c)==(EOF))
#define isdigit(c) ('0'<=(c)&&(c)<='9')
template<class T>inline void rd(T &x){
static bool sign(0);
static char ch(0);
for(x=0,sign=0,ch=getc();!isdigit(ch);ch=getc())if(ch=='-')sign^=1;
for(;isdigit(ch);x=(x<<1)+(x<<3)+(ch^'0'),ch=getc());
return x=sign?-x:x,void();
}
template<class T>inline void wr(T x,char End='\n'){
static short top(0),st[100];
x<0?putc('-'),x=-x:0,top=0;
do st[++top]=x%10,x/=10;while(x);
for(;top;putc(st[top]^'0'),--top);
return putc(End),void();
}
#undef blank
#undef isdigit
}using namespace IOstream;
constexpr int N=50+10,dx[4]= {-1,0,1,0},dy[4]= {0,1,0,-1}; //U,R,D,L
//constexpr ll INF=2e20;
namespace Ex_CRT {
ll Ex_Gcd(ll &x,ll &y,ll a,ll b) {
if(!b)return x=1,y=0,a;
ll G=Ex_Gcd(y,x,b,a%b);
return y-=(a/b)*x,G;
}
bool merge(Pll &A,Pll B) {
A.Fi%=A.Se,B.Fi%=B.Se;
ll x=0,y=0,a=A.Se,b=B.Se,c=B.Fi-A.Fi,g=Ex_Gcd(x,y,a,b);
if(c%g)return 0;
return x*=c/g,x=(x%(b/g)+(b/g))%(b/g),A=(Pll) {a*x+A.Fi,a/g*b},1;
}
Pll CRT(const vector<Pll> &vec) {
Pll res= {0,1};
for(const Pll &x:vec)if(!merge(res,x))return (Pll) {
INF,INF
};
return res;
}
}
int n,m,Q,X,Y;
ll ans=INF;
vector<Pll> Bac[5];
namespace Bacteria {
int turn[N][N];
int dis[N][N][4];
struct Place {
int x,y,d;
Place(int x=0,int y=0,int d=0):x(x),y(y),d(d) {}
Place Nxt() {
Place nxt(x,y,(d+turn[x][y])&3);
if(x+dx[nxt.d]<1||x+dx[nxt.d]>n||y+dy[nxt.d]<1||y+dy[nxt.d]>m)nxt.d^=2;
return nxt.x+=dx[nxt.d],nxt.y+=dy[nxt.d],nxt;
}
} S;
vector<Pll> Constr() {
char C[N];
int Cycle;
vector<Pll> eq;
rd(S.x),rd(S.y),scanf("%s",C),S.d=(C[0]=='U'?0:(C[0]=='R'?1:(C[0]=='D'?2:3)));
FOR(i,1,n) {
scanf("%s",C);
FOR(j,1,m)turn[i][j]=(C[j-1]^'0')&3;
}
RCL(dis,-1,dis,1),dis[S.x][S.y][S.d]=1;
for(Place u=S,v=u.Nxt();; u=v,v=u.Nxt()) {
if(~dis[v.x][v.y][v.d]&&(S=v,Cycle=dis[u.x][u.y][u.d]-dis[v.x][v.y][v.d]+1,1))break;
dis[v.x][v.y][v.d]=dis[u.x][u.y][u.d]+1;
}
FOR(d,0,3)if(~dis[X][Y][d])eq.push_back({dis[X][Y][d],dis[X][Y][d]<dis[S.x][S.y][S.d]?-1:Cycle});
return eq;
}
}
void dfs(int u,vector<Pll> &cur) {
if(u>=Q) {
ll t=-1;
for(const Pll &x:cur)if(!~x.Se&&(t=x.Fi,1))break;
if(~t) {
bool flag=1;
for(const Pll &x:cur)flag&=(!~x.Se?x.Fi==t:t>=x.Fi&&t%x.Se==x.Fi%x.Se);
if(flag)tomin(ans,t);
return;
}
Pll res=Ex_CRT::CRT(cur);
if(res.Fi>=INF&&res.Se>=INF)return;
t=res.Fi;
for(const Pll &x:cur)if(x.Fi>res.Fi)tomax(t,res.Fi+(x.Fi-res.Fi-1+res.Se)/res.Se*res.Se);
return tomin(ans,t),void();
}
for(const Pll &x:Bac[u])cur.push_back(x),dfs(u+1,cur),cur.pop_back();
}
signed main() {
rd(n),rd(m),rd(Q),rd(X),rd(Y);
FOR(i,0,Q-1)Bac[i]=Bacteria::Constr();
vector<Pll> cur;
dfs(0,cur),wr(ans>=INF?-1:ans,'\n');
return 0;
}

浙公网安备 33010602011771号