题意:
由于有
n=x1+x2+..+xk(xi>=0)
n
=
x
1
+
x
2
+
.
.
+
x
k
(
x
i
>=
0
)
,假设
xi=g∗ti
x
i
=
g
∗
t
i
,那么
t1+...tk=n/g
t
1
+
.
.
.
t
k
=
n
/
g
所以系数一共有
C(n/g+k−1,k−1)
C
(
n
/
g
+
k
−
1
,
k
−
1
)
种情况,答案为
2f[g]−1
2
f
[
g
]
−
1
g的倍数时会重复计算g的情况,因此要容斥。所以枚举n的因子时要从小到大枚举。
然后因为 2f[g] 2 f [ g ] 非常大,所以要欧拉降幂。
欧拉降幂公式:
需要注意的是只有在 B>=phi(C) B >= p h i ( C ) 的时候才需要 +phi(C) + p h i ( C ) ,相当于是把所有的数变成了0到 2phi(C) 2 p h i ( C )
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int mod1 = 1e9 + 6;
const int maxn = 2000000 + 5;
const ll inf = 0x3f3f3f3f;
int T, cnt, n, k, p[maxn];
ll fac[maxn], inv[maxn], f[maxn], ff[maxn], dp[maxn];
ll qpow(ll x, ll n) {
ll ans = 1;
while (n) {
if (n & 1) ans = ans * x % mod;
n >>= 1;
x = x * x % mod;
}
return ans;
}
void init() {
f[0] = 0, f[1] = 1; f[2] = 1;
ff[0] = 0, ff[1] = 1, ff[2] = 1;
for (int i = 3; i <= 1000001; i++) {
f[i] = (f[i - 1] + f[i - 2]) % mod1;
ff[i] = min(ff[i - 1] + ff[i - 2], 1ll * inf);
}
fac[0] = fac[1] = 1;
inv[0] = inv[1] = 1;
for (int i = 2; i <= 2000001; i++) fac[i] = fac[i - 1] * i % mod;
for (int i = 2; i <= 2000001; i++) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
for (int i = 2; i <= 2000001; i++) inv[i] = inv[i] * inv[i - 1] % mod;
}
ll C(ll n, ll m) {
ll ans = fac[n];
ans = ans * inv[m] % mod;
ans = ans * inv[n - m] % mod;
return ans;
}
int main() {
#ifdef __APPLE__
freopen("1.in", "r", stdin);
// freopen("1.out", "w", stdout);
#endif
init();
scanf("%d", &T);
while (T--) {
scanf("%d %d", &n, &k);
cnt = 0;
for (int i = 1; i * i <= n; i++) {
if (n % i == 0) {
p[++cnt] = i;
if (i * i < n)
p[++cnt] = n / i;
}
}
sort(p + 1, p + cnt + 1);
for (int i = 1; i <= cnt; i++) {
dp[i] = C(p[i] + k - 1, k - 1);
}
ll ans = 0;
for (int i = 1; i <= cnt; i++) {
ans = (ans + dp[i] * (qpow(2, f[n / p[i]] + (f[n / p[i]] >= mod1) * mod1) - 1 + mod)) % mod;
for (int j = i + 1; j <= cnt; j++) {
if (p[j] % p[i] == 0) {
dp[j] = (dp[j] - dp[i] + mod) % mod;
}
}
}
ans = ans * qpow(C(n + k - 1, k - 1), mod - 2) % mod;
printf("%lld\n", ans);
}
}