首先思考一个非常简单的性质:记 (d=gcd(n,m)),那么每次在一起吃完饭的男女孩编号必定与 (d) 同余,而根据斐蜀定理可以得到另一方面的结论:对于每一个 (mod d) 的剩余类,如果其中至少有一个男孩/女孩是快乐的,那所有与这样的男孩/女孩编号 (mod d) 同余的男孩/女孩最终都会变得快乐。
这样 (-1) 的情况就很好判断了:只要检查每个 (mod d) 的剩余类都至少有一个男孩/女孩是快乐的即可,特别地,如果 (d>b+g) 那答案肯定是 (-1),而显然要解决答案不是 (-1) 的情况,只需要对每个 (mod d) 的剩余类 (x) 都做一遍 (n,m) 的互质的情况,设其答案为 (ans),然后令答案对 (ans imes d+x) 取 (max) 即可。
考虑如何解决 (n,m) 互质的情况,考虑同余最短路(怎么想到的/bx,实是神仙),我们考虑这样建图:
- 对于每个快乐的男孩 (b),连一条 (S o b),权值为 (b) 的边。
- 对于每个快乐的女孩 (g),连一条 (S o gmod n),权值为 (g) 的边,表示这个女孩 (g) 最早会在 (g) 时刻带动男孩 (gmod n) 变得快乐。
- 对于每个男孩 (i),连边 (i o(i+m)mod n),权值为 (m),表示如果 (i) 变得快乐,那么 (m) 时间以后 ((i+m)mod n) 也会变得快乐。
跑最短路即可,最后我们取源点到所有一开始不快乐的男孩距离的最大值,就是所有男孩变得快乐的时间的最大值,然后再对所有女孩做一遍同样的操作即可。
直接建图跑 dijkstra 复杂度是 (nlog n) 的,无法通过。我们发现第三类边构成了一个环,因此这个模型可以视作一个环上加了一些源点连到环上某个点的边,要求源点到所有非关键点的距离最大值,而关键点个数很小,因此我们考虑将关键点压进一个 set
,然后对于两个相邻关键点 (l,r) 路径上的所有点,显然到源点距离最大的肯定是 (r-1),因此我们 (mathcal O(k)) 地算出所有这样的 (r-1) 到源点的距离,然后取 (max) 即可,这样复杂度就降到了 (klog k),其中 (k) 为关键点个数。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
#define mt make_tuple
#define eprintf(...) fprintf(stderr,__VA_ARGS__)
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long double ld;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){return (!x)?void():(recursive_print(x/10),putc(x%10^48),void());}
template<typename T> void print(T x){(!x)&&(putc('0'),0);(x<0)&&(putc('-'),x=~x+1);recursive_print(x);}
template<typename T> void print(T x,char c){print(x);putc(c);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=2e5;
const ll INFll=0x3f3f3f3f3f3f3f3fll;
int n,m,B,G,N,M;
vector<int> b[MAXN+5],g[MAXN+5];
int gcd(int x,int y){return (!y)?x:gcd(y,x%y);}
void exgcd(int x,int y,int &a,int &b){
if(!y) return a=1,b=0,void();exgcd(y,x%y,a,b);
int tmp=a;a=b;b=tmp-(x/y)*b;
}
int getinv(int a,int mod){
int x,y;exgcd(a,mod,x,y);
return (x+mod)%mod;
}
ll solve(vector<int> &b,vector<int> &g,int n,int m){
map<int,bool> in;map<int,int> dis;set<int> pos;
for(int x:b){in[x]=1;pos.insert(x);dis[x]=x;}
for(int x:g){
pos.insert(x%n);
if(!dis.count(x%n)) dis[x%n]=x%n;
else chkmin(dis[x%n],x%n);
} int iv=getinv(m,n);
vector<pair<int,pii> > vec;int pos0=(*pos.begin());
for(int p:pos) vec.pb(mp(1ll*(p-pos0)*iv%n,mp(dis[p],in[p])));
vec.pb(mp(n,mp(0,1)));sort(vec.begin(),vec.end());ll mx=-1;
// for(int i=0;i<vec.size();i++) printf("%d %d %d
",vec[i].fi,vec[i].se.fi,vec[i].se.se);
// printf("
");
for(int i=1;i<vec.size();i++) if(!vec[i-1].se.se||vec[i].fi!=vec[i-1].fi+1)
chkmax(mx,1ll*(vec[i].fi-vec[i-1].fi-1)*m+vec[i-1].se.fi);
// printf("%d
",mx);
return mx;
}
int main(){
scanf("%d%d",&n,&m);int d=gcd(n,m);N=n/d;M=m/d;
if(d>MAXN) return puts("-1"),0;
scanf("%d",&B);for(int i=1,x;i<=B;i++) scanf("%d",&x),b[x%d].pb(x/d);
scanf("%d",&G);for(int i=1,x;i<=G;i++) scanf("%d",&x),g[x%d].pb(x/d);
for(int i=0;i<d;i++) if(b[i].empty()&&g[i].empty()) return puts("-1"),0;
ll res=0;
for(int i=0;i<d;i++){
chkmax(res,1ll*d*solve(b[i],g[i],N,M)+i);
chkmax(res,1ll*d*solve(g[i],b[i],M,N)+i);
} printf("%lld
",res);
return 0;
}