Description
我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案。小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究。然而他很快发现工作量太大了,于是向你寻求帮助。你的任务很简单,小z会告诉你一个整数K,你需要回答他最大公约数刚好为K的选取方案有多少个。由于方案数较大,你只需要输出其除以1000000007的余数即可。
Input
输入一行,包含4个空格分开的正整数,依次为N,K,L和H。
Output
输出一个整数,为所求方案数。
Solution
这里有两种做法,一种是递推:
我们考虑最大公约数为k*i的方案数,表示为f[i]。
明显应有
1
≤
i
≤
h
−
l
1\leq i\leq h-l
1≤i≤h−l
否则只有一种
x
,
x
,
x
,
x
,
x
,
.
.
.
(
i
∣
x
)
x,x,x,x,x,...(i|x)
x,x,x,x,x,...(i∣x)的方案,此时最大公约数为x而非i,不予考虑。
设H=(h-1)/k+1,L=(l-1)/k+1
同样的,计算过程中要去掉这种部分,所以减去H-L+1
那么
f
[
i
]
=
(
H
−
L
+
1
)
n
−
(
H
−
L
+
1
)
−
∑
a
≥
2
k
∗
i
∗
a
≤
h
−
l
f
[
k
∗
i
∗
a
]
f[i]=(H-L+1)^n-(H-L+1)-\sum_{a\geq2}^{k*i*a\leq h-l}f[k*i*a]
f[i]=(H−L+1)n−(H−L+1)−∑a≥2k∗i∗a≤h−lf[k∗i∗a]
从大到小递推即可。
第二种,莫比乌斯反演+杜教筛
中xi表示第i个数的取值。
然后这里就可以分块来求。
由于h的范围过大,所以需要使用杜教筛求mu的前缀和,详见 bzoj3944
Code
只有第一种 不会杜教筛
#include<bits/stdc++.h>
#define mod 1000000007
#define maxn 100000
using namespace std;
long long f[maxn+1];
long long qvod(long long x,long long k){
long long ans=1;
while(k!=0){
if(k&1)ans=ans*x%mod;
x=x*x%mod;
k>>=1;
}
return ans;
}
int main(){
int a,b,k,n;
scanf("%d%d%d%d",&n,&k,&a,&b);
int l=a/k,r=b/k;
if(a%k)l++;
for(int i=maxn;i>=1;i--){
int L=l/i,R=r/i;
if(l%i) L++;
if(l<=r){
f[i]=qvod(R-L+1,n);
f[i]=(f[i]-(R-L+1)+mod)%mod;
for(int j=i*2;j<=maxn;j+=i)
f[i]=(f[i]-f[j]+mod)%mod;
}
}
if(l==1) f[1]++;
printf("%lld",(f[1]+mod)%mod);
}