CodeForces - 1342C Yet Another Counting Problem (数论)
题目大意:给定一个区间以及两个正整数a,b,求这个区间内满足
(
(
x
m
o
d
a
)
m
o
d
b
)
≠
(
(
x
m
o
d
b
)
m
o
d
a
)
((x \space mod \space a) \space mod \space b)\neq((x\space mod \space b)\space mod \space a)
((x mod a) mod b)=((x mod b) mod a)的正整数x的数量。
题解:正难则反。我们可以考虑先计算这个区间内有多少满足
(
(
x
m
o
d
a
)
m
o
d
b
)
=
(
(
x
m
o
d
b
)
m
o
d
a
)
((x \space mod \space a) \space mod \space b)=((x\space mod \space b)\space mod \space a)
((x mod a) mod b)=((x mod b) mod a)的正整数x。不妨设
a
≤
b
a \leq b
a≤b,则有:
x
m
o
d
a
=
(
(
x
m
o
d
b
)
m
o
d
a
)
x
≡
(
x
m
o
d
b
)
m
o
d
a
x \space mod \space a=((x\space mod \space b)\space mod \space a)\\x\equiv (x \space mod \space b)\space mod \space a
x mod a=((x mod b) mod a)x≡(x mod b) mod a
设
x
=
k
b
+
r
,
d
=
g
c
d
(
a
,
b
)
x=kb+r,d=gcd(a,b)
x=kb+r,d=gcd(a,b),
k
b
+
r
≡
r
m
o
d
a
k
b
≡
0
m
o
d
a
k
∗
(
b
/
d
)
≡
0
m
o
d
(
a
/
d
)
k
≡
0
m
o
d
(
a
/
d
)
kb+r\equiv r\space mod \space a\\kb\equiv 0 \space mod \space a\\k*(b/d)\equiv 0\space mod \space (a/d)\\k\equiv0\space mod \space (a/d)
kb+r≡r mod akb≡0 mod ak∗(b/d)≡0 mod (a/d)k≡0 mod (a/d)
问题即转化为:给定一个区间[l,r],存在某类数除以b得到的商可以整除(a/d),设这类数的数量为y,求r-(l-1)-y。我们可以进一步简化问题为:如果有函数cal(x)可以给出关于区间[1,x]的这个问题的答案,那么我们只需要输出cal(r)-cal(l-1)的结果即可。
下面是AC代码。
#include<bits/stdc++.h>
using namespace std;
struct fastio{fastio(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);}}fio;
#define int long long
#define debug(x) cerr<<#x<<":"<<x<<endl
#define endl '\n'
signed main(){
int t,a,b,q,l,r;
cin>>t;
while(t--){
cin>>a>>b>>q;
if(a>b) swap(a,b);
int ap=a/__gcd(a,b);
auto cal=[=](int n)->int{
int k=n/b;
if(k%ap==0) return n-((k/ap)-1)*b-n%b-1;
return n-(k/ap)*b;
};
while(q--){
cin>>l>>r;
cout<<cal(r)-cal(l-1)<<" ";
}
cout<<endl;
}
}