【洛谷 P5330】【SNOI2019】—数论(循环节)

传送门

考虑iia+xpa+xp这样的形式
由于这在对qq取模下是循环的

考虑枚举每个aa,把环找出来
那么对于每个a[i]a[i]
就是询问循环中每个在bb中出现的数出现了多少次

显然一定是一个环总的值的倍数加上一段区间
维护一下的环前缀和就可以了

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
#define gc getchar
#define ll long long
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readl(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
#define poly vector<int>  
#define chemx(a,b) ((a)<(b)?(a)=(b):0)
#define chemn(a,b) ((a)>(b)?(a)=(b):0)
cs int N=1000005;
int p,q,n,m,tot,v[N],a[N],b[N];
vector<int> cir[N],val[N];
vector<ll>s[N];
int buc[N],vis[N],bel[N],pos1[N],pos2[N],sum[N],siz[N];
ll ans,T;
inline int gcd(int a,int b){
	return b?gcd(b,a%b):a;
}
signed main(){
	p=read(),q=read(),n=read(),m=read(),T=readl();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=1;i<=m;i++)b[i]=read(),v[b[i]]=1;
	for(int i=0,x;i<q;i++)if(!vis[i]){
		for(x=i;!vis[x];x=(x+p)%q)
		vis[x]=1;tot++;
		cir[tot].pb(i),bel[i]=tot,val[tot].pb(v[i]),sum[tot]+=v[i],siz[tot]++;
		for(int y=(i+p)%q;y!=x;y=(y+p)%q)
		cir[tot].pb(y),bel[y]=tot,val[tot].pb(v[y]),sum[tot]+=v[y],siz[tot]++;
	}
	for(int i=1;i<=tot;i++){
		for(int j=0,l=cir[i].size()-1;j<=l;j++)
		cir[i].pb(cir[i][j]),val[i].pb(val[i][j]),pos1[cir[i][j]]=j,pos2[cir[i][j]]=cir[i].size()-1;
		for(int j=0;j<=cir[i].size()-1;++j)
		s[i].pb(j==0?val[i][j]:(val[i][j]+s[i][j-1]));
	}
	for(int i=1;i<=n;i++)if(a[i]<=T-1){
		int v=a[i]%q,id=bel[v];
		ll cnt1=(T-1-a[i])/p,cnt2=cnt1/siz[id],res=cnt1%siz[id];
		ans+=1ll*cnt2*sum[id];
		int l=v,r=(1ll*res*p+v)%q;
		if(pos1[l]>pos1[r])
		ans+=s[id][pos2[r]]-s[id][pos1[l]]+::v[l];
		else ans+=s[id][pos1[r]]-s[id][pos1[l]]+::v[l];
	}
	cout<<ans;
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328469.html