[luogu P4240] 毒瘤之神的考验

\(\text{Problem}:\)毒瘤之神的考验

\(\text{Solution}:\)

首先大力推导式子:

\[\begin{aligned} &\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\varphi(ij)\\ &=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\frac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))}\\ &=\sum\limits_{d=1}^{\min(n,m)}\frac{d}{\varphi(d)}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\varphi(i)\varphi(j)[\gcd(i,j)=d]\\ &=\sum\limits_{d=1}^{\min(n,m)}\frac{d}{\varphi(d)}\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{d}\rfloor}\varphi(id)\varphi(jd)[\gcd(i,j)=1]\\ &=\sum\limits_{d=1}^{\min(n,m)}\frac{d}{\varphi(d)}\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{d}\rfloor}\varphi(id)\varphi(jd)\sum\limits_{k\mid \gcd(i,j)}\mu(k)\\ &=\sum\limits_{d=1}^{\min(n,m)}\frac{d}{\varphi(d)}\sum\limits_{k=1}^{\lfloor\frac{\min(n,m)}{d}\rfloor}\mu(k)\sum\limits_{i=1}^{\lfloor\frac{n}{dk}\rfloor}\varphi(idk)\sum\limits_{j=1}^{\lfloor\frac{m}{dk}\rfloor}\varphi(jdk)\\ &=\sum\limits_{T=1}^{\min(n,m)}\sum\limits_{d\mid T}\frac{d\cdot\mu(\frac{T}{d})}{\varphi(d)}\sum\limits_{i=1}^{\lfloor\frac{n}{T}\rfloor}\varphi(iT)\sum\limits_{j=1}^{\lfloor\frac{m}{T}\rfloor}\varphi(jT) \end{aligned} \]

\(f(n)=\sum\limits_{d\mid n}\frac{d\cdot\mu(\frac{n}{d})}{\varphi(d)}\)\(g(n,k)=\sum\limits_{i=1}^{n}\varphi(ik)\),有:

\[\sum\limits_{T=1}^{\min(n,m)}f(T)g(\lfloor\frac{n}{T}\rfloor,T)g(\lfloor\frac{m}{T}\rfloor,T) \]

\(O(n\ln n)\) 的时间复杂度内预处理 \(f\)\(g\),可以得到 \(50\) 分。

\(h(x,y,n)=\sum\limits_{k=1}^{n}f(k)g(x,k)g(y,k)\),那么对原式进行整除分块,有(\(l,r\) 表示当前区间):

\[\sum\limits_{l,r}h(\lfloor\frac{n}{l}\rfloor,\lfloor\frac{m}{l}\rfloor,r)-h(\lfloor\frac{n}{l}\rfloor,\lfloor\frac{m}{l}\rfloor,l-1) \]

显然不能直接预处理 \(h\),但是我们考虑根号分治。设阈值 \(S\),预处理出所有 \(x,y\leq S\)\(h(x,y,n)\),对于剩下的情况暴力计算,可以通过本题。

\(\text{Code}:\)

#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int M=100010, N=100000, S=50, Mod=998244353;
inline int read()
{
	int s=0, w=1; ri char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
	return s*w;
}
int pri[M],cnt,mu[M],phi[M],iiv[M]; bool book[M];
int f[M]; vector<int> g[M]; vector<int> h[S+1][S+1];
inline void Init()
{
	iiv[1]=1;
	for(ri int i=2;i<=N;i++) iiv[i]=1ll*(Mod-Mod/i)*iiv[Mod%i]%Mod;
	mu[1]=phi[1]=1;
	for(ri int i=2;i<=N;i++)
	{
		if(!book[i]) pri[++cnt]=i, mu[i]=-1, phi[i]=i-1;
		for(ri int j=1;j<=cnt&&i*pri[j]<=N;j++)
		{
			book[i*pri[j]]=1;
			if(i%pri[j]) mu[i*pri[j]]=-mu[i], phi[i*pri[j]]=phi[i]*(pri[j]-1);
			else { phi[i*pri[j]]=phi[i]*pri[j]; break; }
		}
	}
	for(ri int i=1;i<=N;i++)
	{
		int w=1ll*i*iiv[phi[i]]%Mod;
		for(ri int j=i;j<=N;j+=i)
		{
			if(!mu[j/i]) continue;
			if(~mu[j/i]) f[j]=(f[j]+w)%Mod;
			else f[j]=(f[j]-w+Mod)%Mod;
		}
	}
	for(ri int i=1;i<=N;i++)
	{
		g[i].eb(0);
		for(ri int j=1,lst=0;j<=N/i;j++)
		{
			(lst+=phi[i*j])%=Mod;
			g[i].eb(lst);
		}
	}
	for(ri int i=1;i<=S;i++)
	{
		for(ri int j=1;j<=S;j++)
		{
			h[i][j].eb(0);
			for(ri int k=1,lst=0;i*k<=N && j*k<=N;k++)
			{
				lst=(lst+1ll*f[k]*g[k][i]%Mod*g[k][j]%Mod)%Mod;
				h[i][j].eb(lst);
			}
		}
	}
}
signed main()
{
	Init();
	for(ri int T=read();T;T--)
	{
		int n,m;
		n=read(), m=read();
		if(n>m) swap(n,m);
		int up=m/S;
		int ans=0;
		for(ri int i=1;i<=up;i++) ans=(ans+1ll*f[i]*g[i][n/i]%Mod*g[i][m/i]%Mod)%Mod;
		for(ri int l=up+1,r;l<=n;l=r+1)
		{
			r=min(n/(n/l),m/(m/l));
			ans=(ans+h[n/l][m/l][r]-h[n/l][m/l][l-1])%Mod;
		}
		printf("%d\n",(ans+Mod)%Mod);
	}
	return 0;
}
posted @ 2021-05-13 10:45  zkdxl  阅读(74)  评论(1编辑  收藏  举报