我们知道
然后常规反演一波
可以得到
然后设
可以调和级数预处理
然后设
因为y的<=n/x, 所以空间和时间都是nlogn的
发现有一些连续的T使x,y是相等的, 可以整除分块
而当T>sqrt(n) 时, x,y的取值是连续的, 我们可以预处理这一部分的答案, 然后整除分块
而当T<sqrt(n) 时, 总共循环T次就可以通过F,G推出答案, 复杂度是正确的
但空间显然开不下, 我们设定一个参数B, B<sqrt(n), 然后S的空间复杂度是B^2*n
#include<bits/stdc++.h>
#define N 100050
#define Mod 998244353
#define LL long long
using namespace std;
const int B = 35;
int prim[N], isp[N], tot, mu[N], phi[N], inv[N];
LL F[N], *G[N], *S[B+1][B+1];
int T;
void prework(){
mu[1] = phi[1] = inv[1] = 1;
for(int i=2;i<=N-50;i++){
if(!isp[i]) prim[++tot] = i, mu[i] = -1, phi[i] = i-1;
for(int j=1;j<=tot;j++){
if(i*prim[j] > N-50) break;
isp[i*prim[j]] = 1;
if(i % prim[j] == 0){ phi[i*prim[j]] = phi[i] * prim[j]; break;}
phi[i*prim[j]] = phi[i] * (prim[j] - 1);
mu[i*prim[j]] = -mu[i];
}
}
for(int i=2;i<=N-50;i++)
inv[i] = Mod - 1ll * Mod / i * inv[Mod%i] % Mod;
for(int i=1;i<=N-50;i++){
for(int j=i;j<=N-50;j+=i){
F[j] = (F[j] + 1ll * mu[j/i] * i % Mod * inv[phi[i]] % Mod) % Mod;
}
}
for(int i=1;i<=N-50;i++){
G[i] = new LL[N/i+1];
G[i][0] = 0;
for(int j=1;j<=N/i;j++){
G[i][j] = (G[i][j-1] + 1ll * phi[i*j]) % Mod;
}
}
for(int j=1;j<=B;j++){
for(int k=1;k<=B;k++){
int len = (N-50) / max(j,k);
S[j][k] = new LL[len+1]; S[j][k][0] = 0;
for(int i=1;i<=len;i++){
S[j][k][i] = (S[j][k][i-1] + F[i] * G[i][j] % Mod * G[i][k] % Mod) % Mod;
}
}
}
}
void Solve(){
int n,m; scanf("%d%d",&n,&m);
if(n>m) swap(n,m);
LL ans = 0;
for(int i=1;i<=m/B;i++){
ans = (ans + F[i] * G[i][n/i] % Mod * G[i][m/i] % Mod) % Mod;
}
for(int l=m/B+1,r;l<=n;l=r+1){
int v1 = n/l, v2 = m/l;
r = min(n/v1, m/v2);
ans += S[v1][v2][r] - S[v1][v2][l-1];
ans = (ans % Mod + Mod) % Mod;
} printf("%lld\n",ans);
}
int main(){
prework(); scanf("%d",&T);
while(T--) Solve(); return 0;
}