这道题的式子可以硬推, 也可以按 (f(gcd(i,j)) = (1*g) (gcd(i,j))) 的套路来快速得出答案(其实总行数没少几行qwq), 不细说。
最后要算的就是:
[sum_{T=1}^{min(n,m)} lfloor frac{n}T
floor lfloor frac{m}T
floor sum_{d|T} d^k mu(frac{T}d)
]
如果去掉(mu(frac{T}d)), 那么我将绝杀, 但是去不得
所以怎么预处理(sum_{d|T} d^k mu(frac{T}d))?
我的方法是把它拆成 (id_k * mu), 就可以 (O(T log log T)) 搞, 可以过。((id_k) 是完全积性函数,可以线性筛出来, 复杂度大约有 (O(n + prime\_cnt log k)))
神仙们的线性筛以后会补qwq
Luogu数据AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e6 + 15;
const int mod = 1000000007;
#define li long long
li ksm(li a, li b, li p) {
li res = 1ll;
for(;b;b>>=1, a=(a*a)%p)
if(b&1) res = (res*a)%p;
return res%p;
}
int t; li k;
int pr_cnt, prime[maxn], v[maxn];
li idk[maxn], g[maxn];
void euler(int n) {
idk[1] = 1ll;
for(int i=2; i<=n; ++i) {
if(!v[i]) {
v[prime[++pr_cnt] = i] = i;
idk[i] = ksm(i, k, mod);
}
for(int j=1; j<=pr_cnt; ++j) {
if(prime[j] > n/i || prime[j] > v[i]) break;
v[prime[j] * i] = prime[j];
idk[prime[j] * i] = idk[i] * idk[prime[j]] % mod;
}
}
for(int i=1; i<=n; ++i) g[i] = idk[i];
for(int i=1; i<=pr_cnt; ++i)
for(int j=n/prime[i]; j>0; --j) {
g[prime[i] * j] -= g[j];
g[prime[i] * j] = (g[prime[i] * j]%mod+mod)%mod;
}
for(int i=2; i<=n; ++i) {
g[i] += g[i-1];
g[i] = (g[i]%mod+mod)%mod;
}
}
int main()
{
cin >> t >> k;
euler(5000000);
while(t--) {
int n, m; scanf("%d%d", &n,&m);
int len = min(n,m);
li ans = 0ll;
for(int i=1,j; i<=len; i=j+1) {
j = min(n/(n/i), m/(m/i));
j = min(j, len);
ans += (g[j]-g[i-1]) * (n/i) % mod * (m/i) % mod;
ans = (ans%mod+mod)%mod;
}
cout << ans << '
';
}
return 0;
}