版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hhhhhhxh/article/details/81516919
题意:
由于有
,假设
,那么
所以系数一共有
种情况,答案为
g的倍数时会重复计算g的情况,因此要容斥。所以枚举n的因子时要从小到大枚举。
然后因为 非常大,所以要欧拉降幂。
欧拉降幂公式:
需要注意的是只有在 的时候才需要 ,相当于是把所有的数变成了0到
#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);
}
}