Luogu4240 毒瘤之神的考验
https://www.luogu.com.cn/problem/P4240
欧拉函数/莫比乌斯反演
结论:
\[\varphi(ij)=\frac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))}
\]
证明见此处
正常操作之后,得到这样一个式子
\[Ans=\sum_{T=1}^n(\sum_{d|T} \frac{d}{\varphi(d)} \mu(\frac{T}{d}))(\sum_{i=1}^{\lfloor \frac{n}{T} \rfloor } \varphi(iT))(\sum_{j=1}^{\lfloor \frac{m}{T} \rfloor } \varphi(jT))\\
令f(n)=\sum_{d|n} \frac{d}{\varphi(d)} \mu(\frac{n}{d}),g(T,n)=\sum_{i=1}^n \varphi(iT)\\
Ans=\sum_{T=1}^n f(T)g(T,\lfloor \frac{n}{T} \rfloor)g(T,\lfloor \frac{m}{T} \rfloor)
\]
我们预处理一部分数据,再暴力枚举其他数据(类似根号优化)
\(C++ Code:\)
#include<cstdio>
#include<iostream>
#include<cmath>
#include<vector>
#define N 100000
#define T 10000
#define B 50
#define ll long long
#define mod (long long)998244353
#define int long long
using namespace std;
int cnt,prime[N+5],phi[N+5],mu[N+5],f[N+5];
int T_T,n,m,b,l,r,x,y;
ll ans,inv[N+5],u[N+5];
bool pri[N+5];
vector<ll>g[N+5],t[B+5][B+5];
void Pre()
{
inv[1]=1;
for (int i=2;i<=N;i++)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
phi[1]=mu[1]=1;
for (int i=2;i<=N;i++)
{
if (!pri[i])
{
prime[++cnt]=i;
phi[i]=i-1,mu[i]=-1;
}
for (int j=1;j<=cnt;j++)
{
ll g=(ll)i*prime[j];
if (g>N)
break;
pri[g]=true;
if (i%prime[j]==0)
{
phi[g]=phi[i]*prime[j];
mu[g]=0;
break;
}
phi[g]=phi[i]*phi[prime[j]];
mu[g]=mu[i]*mu[prime[j]];
}
}
for (int i=1;i<=N;i++)
u[i]=(ll)i*inv[phi[i]]%mod;
for (int i=1;i<=N;i++)
for (int j=1;j*j<=i;j++)
if (i%j==0)
{
f[i]=(f[i]+u[j]*mu[i/j])%mod;
if (j^(i/j))
f[i]=(f[i]+u[i/j]*mu[j])%mod;
f[i]=(f[i]%mod+mod)%mod;
}
for (int i=1;i<=N;i++)
{
int len=N/i;
for (int j=1;j<=len+1;j++)
g[i].push_back(0);
for (int j=1;j<=len;j++)
g[i][j]=(g[i][j-1]+phi[i*j])%mod;
}
for (int i=1;i<=B;i++)
for (int j=i;j<=B;j++)
{
int len=N/j;
for (int k=1;k<=len+1;k++)
t[i][j].push_back(0);
for (int k=1;k<=len;k++)
t[i][j][k]=(t[i][j][k-1]+f[k]*g[k][i]%mod*g[k][j]%mod)%mod;
}
}
signed main()
{
Pre();
scanf("%lld",&T_T);
while (T_T --> 0)
{
scanf("%lld%lld",&n,&m);
if (n>m)
swap(n,m);
ans=0;
for (l=1;l<=n;l=r+1)
{
x=n/l,y=m/l;
r=min(n/x,m/y);
if (m/l<=B)
ans=(ans+t[x][y][r]-t[x][y][l-1])%mod; else
{
for (int i=l;i<=r;i++)
ans=(ans+f[i]*g[i][x]%mod*g[i][y]%mod)%mod;
}
}
ans=(ans%mod+mod)%mod;
cout << ans << endl;
}
return 0;
}