https://www.lydsy.com/JudgeOnline/problem.php?id=4407
题意:很简单不说了。
做法:废话不多说我们开始开心的推公式吧
首先为了方便我把表示
,x=min(n,m),首先我们可以得到:
我们枚举gcd可以得到如下式子:
我们发现后面的那部分可以直接套用莫比乌斯反演的结论:
我们在枚举t可以得到如下式子:
我们发现td不好处理,我们设S=td,枚举S(其实是套路):
我们设,我们发现他是一个积性函数,因此我们可以使用线性筛
同时只要我们发现他的特殊情况的值,就可以使用线性筛了:
同时我们在前面一部分可以使用分块所以总的时间复杂度为
#include "bits/stdc++.h"
using namespace std;
const double eps = 1e-8;
#define reg register
#define lowbit(x) x&-x
#define pll pair<ll,ll>
#define pii pair<int,int>
#define fi first
#define se second
#define makp make_pair
int dcmp(double x) {
if (fabs(x) < eps) return 0;
return (x > 0) ? 1 : -1;
}
typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const ull hash2 = 50331653;
const ll N = 5000000 + 10;
const int M = 1000 + 10;
const int inf = 0x3f3f3f3f;
const ll mod = 1000000000 + 7;
int vis[N], pri[N], phi[N], cnt, mu[N], k;
ll h[N];
void addmod(ll &x) {
if (x >= mod) x -= mod;
}
ll quick(ll a, ll n) {
ll ans = 1;
while (n) {
if (n & 1) ans = ans * a % mod;
n >>= 1;
a = a * a % mod;
}
return ans;
}
void init() {
vis[1] = h[1] = 1;
cnt = 0;
for (int i = 2; i < N; i++) {
if (!vis[i]) {
pri[++cnt] = i;
h[i] = (quick(i, k) - 1 + mod) % mod;
}
for (int j = 1; j <= cnt && i * pri[j] < N; j++) {
vis[i * pri[j]] = 1;
if (i % pri[j] == 0) {
h[i * pri[j]] = h[i] * quick(pri[j], k) % mod;
break;
}
h[i * pri[j]] = h[i] * ((quick(pri[j], k) - 1 + mod) % mod) % mod;
}
}
for (int i = 1; i < N; i++) h[i] += h[i - 1];
}
ll solve(int n, int m) {
ll ans = 0;
int mn = min(n, m);
for (int l = 1, r; l <= mn; l = r + 1) {
r = min(n / (n / l), m / (m / l));
ans += 1LL * (n / l) * (m / l) % mod * (h[r] - h[l - 1]) % mod;
ans %= mod;
}
return ans;
}
int main() {
int T, n, m;
scanf("%d%d", &T, &k);
init();
while (T--) {
scanf("%d%d", &n, &m);
printf("%lld\n", solve(n, m));
}
return 0;
}