输出一个整数,为所求方案数。
2 2 2 4
3
我们把左右区间分别处理: r = r / k; l = (l - 1) / k + 1;
这样问题就转化为求[l,r]区间内,选n个数其最大公约数为1的方案数
因为r-l<=105 所以这个区间内任意两个不相等的数的最大公约数最大不超过(r - l) <= 105 证明很好证:因为两个数p > q的最大公约数如果为x,那么p / x - q / x >= 1,那么p - q >= x、、、、、、
所以可以暴力所有的最大公约数,设[l,r]中选n个不完全相同的数其最大公约数为i的方案数为dp[i]
那么[l,r]中有多少含i因子的数呢?
显然有t = r / i - (l - 1) / i个数
那么dp[i] = tn 种方案,但是这里面肯定有n个数都相同的方案一共有t个,所以dp[i] = (tn - t) % mod;种方案
但是这个时候是所有n个数有i因子的方案数,而不是gcd=i的方案数,所以dp[i] = dp[i] - dp[j](j <= r - l && j | i)
然后这样dp[1]就是正解了
但是我们注意到,我们的dp[1]是在[l,r]中选n个不完全相同的数其最大公约数为i的方案数,但是实际上我们可以让n个数完全相同(假设为x),但是这样的话n个数的gcd就等于x,所以x必须为k,因为求的是gcd=k的方案数
所以当k∈[l,r]时,dp[1] = dp[1] + 1;
代码如下:
#include
#define maxn (100000 + 10)
typedef long long int LLI;
using namespace std;
int dp[maxn];
int p = 1000000007;
LLI Fast_power(LLI n,LLI k,LLI mod) {
LLI re = 1;
n = n % mod;
while(k) {
if(k & 1) re = re * n % mod;
k = k >> 1;
n = n * n % mod;
}
return re;
}
int main() {
// freopen("in.txt","r",stdin);
int l,r,n,k;
bool flag = false;
scanf("%d%d%d%d",&n,&k,&l,&r);
if(k >= l && k <= r) flag = true;
r = r / k;
l = (l - 1) / k;
for(int i = r - l; i >= 1; i --) {
int t = r / i - l / i;
dp[i] = (Fast_power(t,n,p) - t + p) % p;
for(int j = 2; j * i <= r - l; j ++)
dp[i] = (dp[i] - dp[i * j] + p) % p;
}
if(flag == true) dp[1] ++;
printf("%d\n",dp[1] % p);
return 0;
}