有环的东西真(TM)难调……
暴力显然是跑一遍(T),对每个数判断一下。
考虑转化研究对象,变为对于每一个(A[i])有多少(x)满足(0< x< T),(xequiv A[i]mod P)且(x mod Qin B)。
显然可令(x=A[i]+k*P),枚举(k),考虑(k)的上界:取到(left lfloor frac{T-1-A[i]}{P} ight floor)。我们发现(x)肯定会在(mod Q)意义下循环。
其一定在(k*Pequiv 0mod Q)时循环。这样我们可以的得到循环节为(k=frac{Q}{gcd(P,Q)})。
这样我们就可以处理出环,在环上跑(left lfloor frac{T-1-A[i]}{P} ight floor)步,看有多少点可以产生贡献(重复经过也要算贡献)。
拿前缀和维护即可,因为((x+P)\%Q)不好倒回,所以我的前缀和和常用的不太一样。
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
int f=1,w=0;char x=0;
while(x<'0'||x>'9') {if(x=='-') f=-1; x=getchar();}
while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();}
return w*f;
}
const int N=1000010;
int A[N],B[N],Fab[N];
int Col[N],Id[N],S[N];
int P,Q,n,m,T,Cnt,ans;
vector<int> Cir[N],Sum[N];
inline int gcd(int a,int b) {return b?gcd(b,a%b):a;}
signed main(){
#ifndef ONLINE_JUDGE
freopen("A.in","r",stdin);
#endif
P=read(),Q=read(),n=read(),m=read(),T=read();
for(int i=1;i<=n;i++) A[i]=read();
for(int i=1;i<=m;i++) B[i]=read();
if(P>Q) swap(A,B),swap(n,m),swap(P,Q);
for(int i=1;i<=m;i++) Fab[B[i]]=1;
int Len=Q/gcd(P,Q);sort(A+1,A+n+1);
for(int i=0;i<Q;i++)
if(!Col[i])
{
int Tot=0;Col[i]=++Cnt,Id[i]=0;
for(int j=(i+P)%Q;j!=i;j=(j+P)%Q) Id[j]=++Tot,Col[j]=Col[i];
Sum[Col[i]].push_back(0);
for(int j=i;(j+P)%Q!=i;j=(j+P)%Q) Sum[Col[i]].push_back(Sum[Col[i]][Id[j]]+Fab[j]);
for(int j=(i+P)%Q;j!=i;j=(j+P)%Q) S[Col[i]]+=Fab[j];S[Col[i]]+=Fab[i];
Cir[Col[i]].push_back(i);
for(int j=(i+P)%Q;j!=i;j=(j+P)%Q) Cir[Col[i]].push_back(j);
}
for(int i=1;i<=n;i++)
{
int Stp=floor((T-A[i]-1)/P*1.0);
ans+=Stp/Len*S[Col[A[i]]];Stp%=Len;
if(Stp+Id[A[i]]<Len)
{
int End=Cir[Col[A[i]]][Stp+Id[A[i]]];
ans+=Sum[Col[A[i]]][Id[End]]-Sum[Col[A[i]]][Id[A[i]]]+Fab[End];
}
else
{
int End=Cir[Col[A[i]]][(Stp+Id[A[i]])%Len];
ans+=S[Col[A[i]]]-Sum[Col[A[i]]][Id[A[i]]]+Sum[Col[A[i]]][Id[End]]+Fab[End];
}
}
printf("%lld",ans);
}