Yet Another Counting Problem
涉及知识点:
solution:
- \(找到所有的[L,R]区间的x,满足(x\)%\(a)\)%\(b \neq (x\)%\(b)\)%\(a\)
- \(看一下数据范围,L和R都是小于等于1e18,a和b都是小于等于200\)
- \(再看一下公式:(x\)%\(a)\)%\(b \neq (x\)%\(b)\)%\(a\)
- \(假如a = 4,b = 6,那么a和b的最大公约数等于12\)
- \(a = 4,所以x\)%\(a = (x+4)\)%\(a,b = 6,x\)%\(b = (x+6)\)%\(b\)
- \(不难得到x\)%\(a = (x+12)\)%\(a,x\)%\(b = (x+12)\)%\(b\)
- \(那么模数会产生周期性的规律,周期就是a和b的最大公约数\)
- \(同理,第一个\)%\(号和第二个\)%\(号是同周期的,所以我们可以理解为:\)
- \(如果(x\)%\(a)\)%\(b \neq (x\)%\(b)\)%\(a,a和b最大公约数=12,那么(x+12)\)%\(a\)%\(b \neq (x+12)\)%\(b\)%\(a\)
- \(这样我们只要算一个周期即可\)
std:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 505;
ll ans[maxn] , pre[40005];
ll cnt = 0 , gc;
ll solve(ll x){
ll y = x/gc;
int z = x%gc;
ll sum = y*cnt + pre[z];
return sum ;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
ll a,b,q,l,r;
scanf("%lld %lld %lld",&a,&b,&q);
gc = a*b/__gcd(a,b);
cnt = 0;
for(int i=1;i<=gc;i++){
if(i%a%b != i%b%a){
cnt++;
}
pre[i] = cnt;
}
for(int j=1;j<=q;j++){
scanf("%lld %lld",&l,&r);
ans[j] = solve(r) - solve(l-1);
}
for(int j=1;j<=q;j++){
printf("%lld ",ans[j]);
}
printf("\n");
}
return 0;
}