Description
我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案。小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究。然而他很快发现工作量太大了,于是向你寻求帮助。你的任务很简单,小z会告诉你一个整数K,你需要回答他最大公约数刚好为K的选取方案有多少个。由于方案数较大,你只需要输出其除以1000000007的余数即可。
Input
输入一行,包含4个空格分开的正整数,依次为N,K,L和H。
Output
输出一个整数,为所求方案数。
Sample Input
Sample Output
HINT
样例解释
题解
设 $F(x)$ 为 $x\mid gcd$ 的个数, $f(x)$ 为 $gcd=x$ 的个数。
\begin{aligned}F(x)&=\sum_{x\mid d}f(d)\\\Rightarrow f(x)&=\sum_{x\mid d}\mu\left(\frac{d}{x}\right)F(d)\end{aligned}
对于输入 $(N,K,L,H)$ 我们记 $\left\lceil\frac{L}{K}\right\rceil$ 为 $l$ ,记 $\left\lfloor\frac{H}{K}\right\rfloor$ 为 $h$ 。
提出 $K$ ,答案就是 $$f(1)=\sum_{i=1}^{h}\mu(i)F(i)$$
显然 $F(i)=\left(\left\lfloor\frac{h}{i}\right\rfloor-\left\lfloor\frac{l-1}{i}\right\rfloor\right)^N$
由于 $h$ 很大,我们还是不能枚举这个 $i$ 。考虑到这样一个问题:当 $i$ 很大时 $\left\lfloor\frac{h}{i}\right\rfloor-\left\lfloor\frac{l-1}{i}\right\rfloor$ 会变成 $0$ 或 $1$ 。实际上只要 $i>h-l$ 数值就为 $0$ 或 $1$ 了。
那么现在答案就变成了 \begin{aligned}&\sum_{i=1}^{h-l}\mu(i)\left(\left\lfloor\frac{h}{i}\right\rfloor-\left\lfloor\frac{l-1}{i}\right\rfloor\right)^N+\sum_{i=h-l+1}^h\mu(i)\left\lfloor\frac{h}{i}\right\rfloor-\left\lfloor\frac{l-1}{i}\right\rfloor\\=&\sum_{i=1}^{h-l}\mu(i)\left(\left\lfloor\frac{h}{i}\right\rfloor-\left\lfloor\frac{l-1}{i}\right\rfloor\right)^N+\sum_{i=1}^h\mu(i)\left\lfloor\frac{h}{i}\right\rfloor-\left\lfloor\frac{l-1}{i}\right\rfloor-\sum_{i=1}^{h-l}\mu(i)\left\lfloor\frac{h}{i}\right\rfloor-\left\lfloor\frac{l-1}{i}\right\rfloor\end{aligned}
我们观察到式子 $\sum\limits_{i=1}^h\mu(i)\left\lfloor\frac{h}{i}\right\rfloor-\left\lfloor\frac{l-1}{i}\right\rfloor$ 的含义就是 $l\sim r$ 区间内有是否有值为 $1$ ,所以等价于 $[L\leq K\wedge K\leq H]$ 。
所以 $$ans=\sum_{i=1}^{h-l}\mu(i)\left(\left(\left\lfloor\frac{h}{i}\right\rfloor-\left\lfloor\frac{l-1}{i}\right\rfloor\right)^N-\left(\left\lfloor\frac{h}{i}\right\rfloor-\left\lfloor\frac{l-1}{i}\right\rfloor\right)\right)+[L\leq K\wedge K\leq H]$$
1 //It is made by Awson on 2018.1.24 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <cstdio> 9 #include <string> 10 #include <vector> 11 #include <cstdlib> 12 #include <cstring> 13 #include <iostream> 14 #include <algorithm> 15 #define LL long long 16 #define Abs(a) ((a) < 0 ? (-(a)) : (a)) 17 #define Max(a, b) ((a) > (b) ? (a) : (b)) 18 #define Min(a, b) ((a) < (b) ? (a) : (b)) 19 #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b)) 20 #define writeln(x) (write(x), putchar('\n')) 21 #define lowbit(x) ((x)&(-(x))) 22 using namespace std; 23 const int N = 1e5; 24 const int MOD = 1000000007; 25 void read(int &x) { 26 char ch; bool flag = 0; 27 for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar()); 28 for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar()); 29 x *= 1-2*flag; 30 } 31 void write(LL x) { 32 if (x > 9) write(x/10); 33 putchar(x%10+48); 34 } 35 36 int n, k, l, h, mu[N+5]; 37 int isprime[N+5], prime[N+5], tot; 38 39 void get_mu() { 40 memset(isprime, 1, sizeof(isprime)); isprime[1] = 0, mu[1] = 1; 41 for (int i = 2; i <= N; i++) { 42 if (isprime[i]) prime[++tot] = i, mu[i] = -1; 43 for (int j = 1; j <= tot && i*prime[j] <= N; j++) { 44 isprime[i*prime[j]] = 0; 45 if (i%prime[j]) mu[i*prime[j]] = -mu[i]; 46 else {mu[i*prime[j]] = 0; break; } 47 } 48 } 49 } 50 int quick_pow(int a, int b) { 51 int ans = 1; 52 while (b) { 53 if (b&1) ans = (LL)ans*a%MOD; 54 a = (LL)a*a%MOD, b >>= 1; 55 } 56 return ans; 57 } 58 void work() { 59 get_mu(); read(n), read(k), read(l), read(h); 60 int flag = (l <= k && k <= h), ans = 0; 61 l = ceil(1.*l/k), h = (h/k); 62 for (int i = 1; i <= h-l; i++) ans = (ans+(LL)mu[i]*quick_pow(h/i-(l-1)/i, n)%MOD)%MOD; 63 for (int i = 1; i <= h-l; i++) ans = (ans-(LL)mu[i]*(h/i-(l-1)/i)%MOD)%MOD; 64 writeln((ans+flag+MOD)%MOD); 65 } 66 int main() { 67 work(); 68 return 0; 69 }