1. 程式人生 > 實用技巧 >「APIO2019」奇怪裝置

「APIO2019」奇怪裝置

「APIO2019」奇怪裝置

找到迴圈就很簡單了

很顯然\(y\)是每\(B\)次一迴圈的,對於每個相鄰的\(y\)迴圈\(x\)的值均相差\(B+1 \pmod A\)

因此總的迴圈就是\(B+1\)對於\(A\)的迴圈乘上\(B\)

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

知道迴圈節之後,把查詢分成\(O(n)\)個區間,排序之後直接解決即可

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

以下是快排版本

#include<bits/stdc++.h>
using namespace std;
using ll=long long;
#define mp make_pair
char IO;
ll rd(){
	ll s=0;
	while(!isdigit(IO=getchar()));
	do s=(s<<1)+(s<<3)+(IO^'0');
	while(isdigit(IO=getchar()));
	return s;
}
int n,c,i;
ll A,B,ans,r=-1,L,R;
pair <ll,ll> S[2000010];
int main(){
	for(n=rd(),A=rd(),B=rd(),A=min(1.0*B*(A/__gcd(A,B+1)),1e18),i=1;i<=n;++i) {
		L=rd(),R=rd();
		if(R-L+1>=A) return printf("%lld\n",A),0;
		L%=A,R%=A;
		L<=R?S[++c]=mp(L,R):(S[++c]=mp(L,A-1),S[++c]=mp(0,R));
	}
	for(sort(S+1,S+c+1),i=1;i<=c;++i) if(r<=S[i].second) ans+=S[i].second-max(r,S[i].first-1),r=S[i].second;
	printf("%lld\n",ans);
}