专栏文章
题解:P5330 [SNOI2019] 数论
P5330题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @min29xz1
- 此快照首次捕获于
- 2025/12/01 19:23 3 个月前
- 此快照最后确认于
- 2025/12/01 19:23 3 个月前
依旧喵喵题。
首先考虑怎么刻画取模之后的限制,我们考虑进行图论建模,对 内每一个数建一个点,然后每个点 连一个指向 的出边,于是这个图会被分成 个环,每个环长是 。
然后我们在环上刻画我们需要的条件。我们枚举一个起始点 ,然后每次在环上跳,跳 次相当于跳到 ,最多能跳 次,每个跳到的 就是合法的。
于是就很简单了,我们处理出来环上 的个数,然后对于一个 我们只需要知道统计整环的个数和环上的一段,用前缀和统计即可。
时间复杂度 。
CPPconst int N=1e6+5,inf=1e9+7;
ll p,q,n,m,t,len;
ll a[N],b[N];
ll seq[N],pre[N],sum[N];
bool tag[N],vis[N];
ll query(ll x,ll L){
if(!L)return 0;
ll y=(x+(L-1)*p)%q;
if(L+seq[x]>len)return sum[x]-(pre[x]-pre[y]-tag[x]);
return pre[y]-pre[x]+tag[x];
}
int main(){
p=read(),q=read(),n=read(),m=read(),t=read();
if(p>q){
swap(p,q),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++)tag[b[i]]=1;
for(int i=0;i<q;i++)if(!vis[i]){
int u=i,v=(u+p)%q;
while(!vis[u]){
vis[u]=1,seq[v]=seq[u]+1;
pre[v]=pre[u]+tag[v];
u=v,v=(u+p)%q;
}
v=(i+p)%q,sum[i]=pre[i],pre[i]=seq[i]=0;
while(v!=i)sum[v]=sum[i],v=(v+p)%q;
}
len=q/__gcd(p,q);
ll ans=0;
for(int i=1;i<=n;i++)if(t-1>=a[i]){
ll st=(t-1-a[i])/p+1;
ans+=(st/len)*sum[a[i]]+query(a[i],st%len);
}
printf("%lld\n",ans);
return 0;
}
// think twice,code once
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...