题意
在区间中选
个数,这
个数
的种数
数据范围:
题解
一看到求的个数——莫比乌斯反演
再看看收据范围——emmm杜教筛
用杜教筛也是可行的,但注意到条件中有一个,现在考虑如何使用这个条件
我们可以注意到需要杜教筛的情况是左右
而这里有个结论,若,
利用这个我们就可以缩小数据范围了,我们先将区间变为,问题就变为求互素组的个数
设表示
且
不全相同的个数;
表示
且
不全相同的个数
那么利用容斥就求得了,最后特判全部相同的情况(能否全部为
)即可
PS:这么设出来的也是可以反演分块求的(不用杜教筛)
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
using LL = long long;
const int MOD = 1e9 + 7;
const int MAXN = 1e5 + 5;
LL N, K, L, H, ans;
LL f[MAXN], F[MAXN];
LL qpow(LL, LL);
int main(){
cin >> N >> K >> L >> H;
if(L % K == 0) L /= K; else L = L / K + 1;
H /= K;
LL i, j;
for(i = 1; i <= MAXN - 5; i++){
LL cnt = (H / i) - (L - 1) / i;
F[i] = (qpow(cnt, N) - cnt + MOD) % MOD;
}
for(i = H - L; i >= 1; i--){
f[i] = F[i];
for(j = 2 * i; j <= H - L; j += i)
f[i] = (f[i] - f[j] + MOD) % MOD;
}
ans = f[1];
if(L == 1) ans++, ans %= MOD;
cout << ans << endl;
return 0;
}
LL qpow(LL x, LL n){
LL res = 1;
while(n){
if(n & 1) res = res * x % MOD;
x = x * x % MOD;
n >>= 1;
}
return res;
}