题目链接:Problem - G - Codeforces
解题思路:
1.先暴力打表看看有没有规律,当k=15,17时发现循环节分别为16和32。(k为2的n次方时,一个都没有。)
发现循环节的规律为k的二进制数的n次。
2.对一个循环的所以结果进行前缀和的操作,得出一个循环能有多少个gcd为1的。
3.找到左边界和右边界中有多少个循环节,再对l和r进行模的处理,得出答案。
时间复杂度O1。
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e6+5;
int n,k,l,r;
int a[N];
int cmp(int x){
int ans=1;
while(x){
x/=2;
ans*=2;
}
return ans;
}
void check(int x){
for(int i=1;i<=x;i++){
if(__gcd(((i*k)^(k)),k)==1){
a[i]=a[i-1]+1;
}else{
a[i]=a[i-1];
}
}
}
signed main(){
cin>>k>>n;
int x=cmp(k);
check(x);
while(n--){
cin>>l>>r;
int ans=0;
l--;
ans+=(r/x)*a[x];
ans+=a[r%x];
ans-=(l/x)*a[x];
ans-=a[l%x];
cout<<ans<<endl;
}
return 0;
}