洛谷P5444 [APIO2019] 奇怪装置 题解

发布时间 2023-10-10 16:26:39作者: xuantianhao

奇怪装置

找到循环就很简单了。

很显然 \(y\) 是每 \(B\) 次一循环的,对于每个相邻的 \(y\) 循环 \(x\) 的值均相差 \(B+1(\bmod A)\)

因此总的循环就是 \(B+1\) 对于 \(A\) 的循环乘上 \(B\)

\(\frac{A}{\gcd(A,B+1)} \times B\)

知道循环节之后,把查询分成 \(O(n)\) 个区间,排序之后直接解决即可。

如果使用基数排序即可做到 \(O(n)\)

以下是快排版本:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e6+100;
int n,A,B,cnt,res;
int r=-1,L,R;
pair<int,int> s[N];
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n>>A>>B;
	A=min(1.0*B*(A/__gcd(A,B+1)),1e18);
	for(int i=1;i<=n;++i) {
		cin>>L>>R;
		if(R-L+1>=A){
			cout<<A;
			return 0;
		}
		L%=A;R%=A;
		if(L<=R) s[++cnt]=make_pair(L,R);
		else{
			s[++cnt]=make_pair(L,A-1);
			s[++cnt]=make_pair(0,R);
		}
	}
	sort(s+1,s+cnt+1);
	for(int i=1;i<=cnt;++i){
		if(r<=s[i].second){
			res+=s[i].second-max(r,s[i].first-1);
			r=s[i].second;
		}
	}
	cout<<res;
	return 0;
}