传送门
原来APIO也有签到题
题解:
首先分析性质,整除同余问题里面有计数那最重要的肯定就是循环节。
考虑一下什么时候 t1 和 t2 形成的数对相同。
⎩⎨⎧t1+⌊Bt1⌋t1≡≡t2+⌊Bt2⌋t2(modA)(modB)
设t2=t1+B⋅x,考虑第一个式子:
t1+⌊Bt1⌋A≡t1+B⋅x+⌊Bt1+B⋅x⌋∣x(B+1)(modA)
其实很容易发现了x的合法取值就是gcd(A,B+1)A∣x,并且容易循环节就是t→t+B⋅x,则最小循环节长度就是gcd(A,B+1)AB。
则中间的部分很容易转化成线段覆盖,直接按照左端点排个序然后覆盖就行了。
注意循环节长度可能炸long long ,直接和最大的右端点取一下min即可。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
inline char gc(){
static cs int Rlen=4e7+7;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T get(){
char c;T num;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int gi(){return get<int>();}
inline ll gl(){return get<ll>();}
}
using namespace IO;
using std::cerr;
using std::cout;
using pii=std::pair<ll,ll>;
#define fi first
#define se second
int n;ll A,B,M;
std::vector<pii> vec;
signed main(){
#ifdef zxyoi
freopen("machine.in","r",stdin);
#endif
n=gi(),A=gl(),B=gl();
M=std::min(1.*A/std::__gcd(A,B+1)*B,1e18+5);
while(n--){
ll l=gl(),r=gl();
if(r-l+1>=M){
cout<<M,exit(0);
}if(r>=M)l%=M,r%=M;
if(l<=r)vec.push_back(pii(l,r));
else vec.push_back(pii(0,r)),vec.push_back(pii(l,M-1));
}
ll nl=0,nr=-1,ans=0;
std::sort(vec.begin(),vec.end());
for(auto &t:vec){
if(t.fi<=nr)nr=std::max(nr,t.se);
else ans+=nr-nl+1,nl=t.fi,nr=t.se;
}ans+=nr-nl+1;cout<<ans;
return 0;
}