一. 前置知识
整除分块:
参考:https://www.cnblogs.com/peng-ym/p/8661118.html
二.题目描述
题目链接: C GCD
给定
l
,
r
,
k
l,r,k
l,r,k,三个整数,在区间
[
l
,
r
]
[l,r]
[l,r]中选
k
k
k个数,一共有多少种公因子?
三.思路
如果判断 一个数
x
x
x是否可以作为 公因子,那么他在
[
l
,
r
]
[l,r]
[l,r],至少有
k
k
k个数是
x
x
x的倍数,即
r
/
x
−
(
l
−
1
)
/
x
>
=
k
r/x-(l-1)/x>=k
r/x−(l−1)/x>=k
其中,
l
−
1
l-1
l−1是为了找小于
l
l
l的
x
x
x的倍数的个数。
那么我们枚举
[
1
,
r
]
[1,r]
[1,r]中的所有数,满足上式的数的个数即为ans。
由于
1
≤
l
≤
r
≤
1
0
12
1≤l≤r≤10^{12}
1≤l≤r≤1012,不能直接遍历,所以用整除分块时间复杂度降到
O
(
n
)
O(\sqrt{n})
O(n)。
四.Code
#include <bits/stdc++.h>
using namespace std;
const double pi = acos(-1.0);
#define x first
#define y second
#define LL long long
#define pb push_back
#define all(v) (v).begin(),(v).end()
#define PII pair<int,int>
#define ll_INF 0x7f7f7f7f7f7f7f7f
#define INF 0x3f3f3f3f
#define debug(x) cerr << #x << ": " << x << endl
#define io ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
LL Mod(LL a,LL mod){return (a%mod+mod)%mod;}
LL fpower(LL a,LL b,LL mod) {LL ans = 1; while(b){ if(b & 1) ans = ans * (a % mod) % mod; a = a % mod * (a % mod) % mod; b >>= 1;} return ans; }
int _;
LL l,r,k;
void solve()
{
//r/i-(l-1)/i>=k;
cin>>l>>r>>k;
LL res=0;
for(LL i=1,j;i<=r;i=j+1)
{
if(i<l)j=min(r/(r/i),(l-1)/((l-1)/i));
else j=r/(r/i);
res+=(j-i+1)*((r/i)-((l-1)/i)>=k);
}
cout<<res<<endl;
}
int main()
{
io;
solve();
return 0;
}
五.总结
这题是采用整出分块进行优化,并非核心思路。