正解:数论
解题报告:
,,,这题还蛮妙的$QwQ$(,,,其实所有数论题对我来说都挺妙的$kk$然后我真的好呆昂我理解了好久$QAQ$
考虑先建$Q$个点,编号为$[0,Q)$,表示膜$Q$的余数.然后每个点$i$向$(i+P) mod Q$连边$QwQ$
显然这个是会成环的,事实上这个环的长度就$frac{Pcdot Q}{gcd(P,Q)}$(不明白的可以去康那道很古早的考过好几遍了的跑跑步那题?那题不是证了个结论是说.在膜$Q$意义下每次走$P$,只会有$gcd(P,Q)$个环嘛,放到这题里就是有$gcd(P,Q)$个长度为$frac{Pcdot Q}{gcd(P,Q)}$的环$QwQ$
然后枚举膜$P$的余数$a_i$,显然顺着边跑就等同于$a_i$不变,然后现在就变成,从$a_i$开始在环中跑$lfloorfrac{T-1-a_i}{P} floor$步,问有多少步是跑到的编号膜$Qin B$的点上$QwQ$
所以考虑先预处理一个环中的属于$B$的数的数量,然后最后剩下的一点小尾巴特殊算下就欧克
$over$!
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<vector> using namespace std; #define il inline #define rg register #define gc getchar() #define int long long #define ri register int #define rb register bool #define rc register char #define rp(i,x,y) for(rg int i=x;i<=y;++i) #define my(i,x,y) for(rg int i=x;i>=y;--i) #define ub(i,x) upper_bound(G[i].begin(),G[i].end(),x)-G[i].begin() const int N=1e6+10; int P,Q,n,m,T,d,len,a[N],id[N],as; bool b[N]; vector<int>G[N]; il int read() { rg char ch=gc;rg int x=0;rg bool y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:-x; } int gcd(ri x,ri y){return y?gcd(y,x%y):x;} signed main() { P=read();Q=read();n=read();m=read();T=read()-1;rp(i,1,n)a[i]=read();rp(i,1,m)b[read()]=1;d=gcd(P,Q);len=P*Q/d; rp(i,0,d-1){ri cnt=0,nw=i;while(!cnt || nw!=i){id[nw]=++cnt;if(b[nw])G[i].push_back(cnt);nw=(nw+P)%Q;}} rp(i,1,n) { ri num=(T-a[i])/len,to=(T-num*len-a[i])/P;as+=num*(int)(G[a[i]%d].size()); ri l=id[a[i]],r=id[(to*P+a[i])%Q]; if(l<=r){as-=ub(a[i]%d,l-1);as+=ub(a[i]%d,r);} else{swap(l,r);as+=(int)(G[a[i]%d].size());++l;--r;if(l>r)continue;as+=ub(a[i]%d,l-1);as-=ub(a[i]%d,r);} } printf("%lld ",as); return 0; }