传送门
题意
问 l l l到 r r r内有多少个数满足 ( ( x m o d a ) m o d b ) ≠ ( ( x m o d b ) m o d a ) ((x\ mod\ a)\ mod\ b)\ \neq\ ((x\ mod\ b)\ mod\ a) ((x mod a) mod b) = ((x mod b) mod a)
思路
发现当为
l
c
a
(
a
,
b
)
lca(a,b)
lca(a,b)倍数的时候,再连续
b
b
b个数字,是那个式子满足相等的。说明循环周期是一个
l
c
m
lcm
lcm
我们可以使用前缀和处理出
1
−
a
∗
b
1-a*b
1−a∗b中符合条件的数,对于
l
l
l和
r
r
r,只需要计算
f
[
m
i
n
(
n
,
c
n
t
)
−
1
]
∗
[
c
n
t
/
(
a
∗
b
)
+
f
[
c
n
t
m
o
d
(
a
∗
b
)
]
f[min(n,cnt)-1]*[cnt/(a*b)+f[cnt\ mod\ (a*b)]
f[min(n,cnt)−1]∗[cnt/(a∗b)+f[cnt mod (a∗b)]
最终答案即
c
a
l
c
(
r
)
−
c
a
l
c
(
l
−
1
)
calc(r)-calc(l-1)
calc(r)−calc(l−1)
代码
ll gcd(ll a,ll b){
return !b?a:gcd(b,a%b);
}
ll a,b,q,l,r,lc;
ll s[maxn];
void init(){
for(int i=1;i<=lc;i++){
s[i]=s[i-1]+(i%a%b!=i%b%a);
}
}
ll cal(ll x){
return s[lc]*(x/lc)+s[x%lc];
}
int main(){
int t;
cin>>t;
while(t--){
scanf("%lld%lld%lld",&a,&b,&q);
lc=a*b/gcd(a,b);//最小公倍数
init();
while(q--){
scanf("%lld%lld",&l,&r);
printf("%lld ",cal(r)-cal(l-1));
}
printf("\n");
}
}