题解 P5330 【[SNOI2019]数论】
题意
求
首先对一个模型作介绍。
对于
说明:
每一个点走若干个
假设
在这个图上考虑问题,我们可以枚举
要解决的问题直观了起来。我们可以在图上标记所有
对于
要注意的是:前缀和中选定的起点值是
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
typedef long long ll;
const int N = 1000001;
inline ll read() {
ll x = 0, f = 1; char ch = getchar();
while(ch > '9' || ch < '0') { if(ch == '-') f = -1; ch = getchar(); }
do x = x * 10 + ch - 48, ch = getchar(); while(ch >= '0' && ch <= '9');
return x * f;
}
int gcd(int x,int y) { return !y ? x : gcd(y,x % y); }
int P,Q,n,m,a[N],b[N]; ll t;
int vis[N],at[N]; ll dist[N],ring[N],sum[N],len;
ll Prefix(ll a,ll x) {
if(!x) return 0;
ll b = (a + (x - 1) * P) % Q;
if(x + dist[a] > len) return sum[a] - (ring[a] - ring[b] - at[a]);
else return ring[b] - ring[a] + at[a];
}
ll Calc(ll T) {
ll ans = 0;
for(int i = 1;i <= n;i++) {
if(T < a[i]) continue;
ll st = (T - a[i]) / P + 1;
ans += st / len * sum[a[i]] + Prefix(a[i],st % len);
}
return ans;
}
int main() {
P = read(), Q = read(), n = read(), m = read(), t = read();
if(P > Q) {
std::swap(P,Q), std::swap(n,m);
for(int i = 1;i <= m;i++) b[i] = read();
for(int i = 1;i <= n;i++) a[i] = read();
} else {
for(int i = 1;i <= n;i++) a[i] = read();
for(int i = 1;i <= m;i++) b[i] = read();
}
for(int i = 1;i <= m;i++) at[b[i]] = true;
for(int i = 0;i < Q;i++) if(!vis[i]) {
int p = i, k = (i + P) % Q;
while(!vis[p]) {
vis[p] = true, dist[k] = dist[p] + 1;
ring[k] = ring[p] + at[k];
p = k, k = (k + P) % Q;
}
k = (i + P) % Q, sum[i] = ring[i], ring[i] = dist[i] = 0;
while(k != i) sum[k] = sum[i], k = (k + P) % Q;
}
len = Q / gcd(P,Q);
std::printf("%lld\n",Calc(t - 1));
return 0;
}