P5330 [SNOI2019] 数论 - 数论
题意
给定 \(p,q,T\) 和正整数集 \(A,B\),求:
\[\sum_{i=0}^{T-1} [(i\bmod p)\in A\land (i\bmod q)\in B] \]\(1\le p,q\le 10^6,1\le T\le 10^{18}\)。
题解
这题代码应该挺简单啊,为啥我就是写不出来。
若 \(p>q\) 则会出现多个 \(a_i\) 在模 \(q\) 意义同余的情况,此时要交换 \(p,q\) 和 \(A,B\)。
我们建一张 \(q\) 个点的图,编号 \(0\dots (q-1)\)。对于点 \(i\),我们从 \(i\) 向 \((i+p)\bmod q\) 连边。那么图中会有若干个环。显然,每个环内的数都是 \((a+bp)\bmod q\) 的形式,且相同的环内的数有相同的 \(a\)。
我们枚举 \(A\) 中的元素。对于元素 \(x\),我们需要统计出有多少非负整数 \(k\) 使得 \(x+kp
代码
#include
#include
#include
#include
using namespace std;
#define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
#define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
#define Debug(...) fprintf(stderr,__VA_ARGS__)
typedef long long ll;
const int V=1e6+5;
int p,q,n,m,a[V],b[V],in[V],pos[V];
ll T,val[V];
int col[V],blcnt;
vector bl[V];
void Dfs(int u){
if(col[u]) return;
col[u]=blcnt,bl[blcnt].push_back(u),pos[u]=bl[blcnt].size()-1;
val[blcnt]+=in[u];
Dfs((u+p)%q);
}
vector s[V];
ll Count(int ring,int x,int d){
if(!d) return 0;
return s[ring][pos[x]+d-1]-(pos[x]?s[ring][pos[x]-1]:0);
}
int main(){
ios::sync_with_stdio(false),cin.tie(nullptr);
cin>>p>>q>>n>>m>>T;
For(i,1,n) cin>>a[i];
For(i,1,m) cin>>b[i];
if(p>q) swap(p,q),swap(a,b),swap(n,m);
For(i,1,m) in[b[i]]=1;
For(i,0,q-1) if(!col[i]) ++blcnt,Dfs(i);
For(i,1,blcnt){
s[i].push_back(in[bl[i].front()]);
for(auto it=next(bl[i].begin());it!=bl[i].end();++it){
s[i].push_back(s[i].back()+in[*it]);
}
for(auto it=bl[i].begin();it!=bl[i].end();++it){
s[i].push_back(s[i].back()+in[*it]);
}
}
ll ans=0;
For(i,1,n){
ll lim=(T-1-a[i])/p+1,len=bl[col[a[i]]].size();
if(T-1-a[i]>=0) ans+=Count(col[a[i]],a[i],lim%len)+lim/len*val[col[a[i]]];
}
cout<