[洛谷]P4240 毒瘤之神的考验-数论

版权声明:转载注明出处,谢谢,有问题可以向博主联系 https://blog.csdn.net/VictoryCzt/article/details/85043474

题目地址

题意简述

T T 次询问,每次给定 n , m n,m ,求下面式子的值:
i = 1 n j = 1 m φ ( i j ) \sum_{i=1}^n\sum_{j=1}^m\varphi(ij)

n , m 1 0 5 n,m\leq 10^5 ,输出答案在 m o d    998244353 \mod 998244353 意义下的值。


分析:

我们先要将 φ ( i j ) \varphi(ij) 拆开,根据定义式:
φ ( n ) = n p n p 1 p p n \varphi(n)=n\prod_{p|n}\frac{p-1}{p}\\ 其中p为n的不同的质数因子

那么我们看 φ ( i ) φ ( j ) \varphi(i)\varphi(j) 就为:

i p i p 1 p j q j q 1 q i\prod_{p|i}\frac{p-1}{p}\cdot j\prod_{q|j}\frac{q-1}{q}

我们将 i j ij 放在一起可以发现:

i j p i p 1 p q j q 1 q ij\prod_{p|i}\frac{p-1}{p}\prod_{q|j}\frac{q-1}{q}

i , j i,j 的质因子可以看成属于 i × j i\times j 的所有质因子,而既属于 i i 又属于 j j 的,也就是属于 g c d ( i , j ) gcd(i,j) 的质因子会被算两次,所以,原式可以转化为:

i j p i j p 1 p q g c d ( i , j ) q 1 q ij\prod_{p|ij}\frac{p-1}{p}\prod_{q|gcd(i,j)}\frac{q-1}{q}

那么,我们将原等式两端同时乘以一个 g c d ( i , j ) gcd(i,j) 可以得到:

φ ( i ) φ ( j ) g c d ( i , j ) = i j p i j p 1 p g c d ( i , j ) q g c d ( i , j ) q 1 q \varphi(i)\varphi(j)gcd(i,j)=ij\prod_{p|ij}\frac{p-1}{p}gcd(i,j)\prod_{q|gcd(i,j)}\frac{q-1}{q}

我们将其替换为 φ ( i j ) \varphi(ij) φ ( g c d ( i , j ) ) \varphi(gcd(i,j)) ,就可以得到:

φ ( i ) φ ( j ) g c d ( i , j ) = φ ( i j ) φ ( g c d ( i , j ) ) φ ( i j ) = φ ( i ) φ ( j ) g c d ( i , j ) φ ( g c d ( i , j ) ) \varphi(i)\varphi(j)gcd(i,j)=\varphi(ij)\varphi(gcd(i,j))\\ \varphi(ij)=\frac{\varphi(i)\varphi(j)gcd(i,j)}{\varphi(gcd(i,j))}

所以我们可以将原式拆开,转化成求:

i = 1 n j = 1 m φ ( i ) φ ( j ) g c d ( i , j ) φ ( g c d ( i , j ) ) \sum_{i=1}^n\sum_{j=1}^m\frac{\varphi(i)\varphi(j)gcd(i,j)}{\varphi(gcd(i,j))}

根据反演题目的套路,我们转换为枚举 g c d ( i , j ) gcd(i,j) ,原式就变为(这里默认 n m n\leq m 如果不满足就交换):

= d = 1 n i = 1 n j = 1 m φ ( i ) φ ( j ) d φ ( d ) [ g c d ( i , j ) = d ] = d = 1 n d φ ( d ) i = 1 n j = 1 m φ ( i ) φ ( j ) [ g c d ( i , j ) = d ] = d = 1 n d φ ( d ) i = 1 n d i = 1 m d φ ( i d ) φ ( j d ) [ g c d ( i , j ) = 1 ] =\sum_{d=1}^{n}\sum_{i=1}^n\sum_{j=1}^m\frac{\varphi(i)\varphi(j)d}{\varphi(d)}[gcd(i,j)=d]\\ = \sum_{d=1}^{n}\frac{d}{\varphi(d)}\sum_{i=1}^n\sum_{j=1}^m\varphi(i)\varphi(j)[gcd(i,j)=d]\\ = \sum_{d=1}^n\frac{d}{\varphi(d)}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{i=1}^{\lfloor\frac{m}{d}\rfloor}\varphi(id)\varphi(jd)[gcd(i,j)=1]

然后就是经典的莫比乌斯反演的套路了,我们将后面的两个求和反演后得到(其中 w g c d ( i , j ) = w i , w j w|gcd(i,j)=w|i,w|j ):

i = 1 n d i = 1 m d φ ( i d ) φ ( j d ) [ g c d ( i , j ) = 1 ] = i = 1 n d i = 1 m d φ ( i d ) φ ( j d ) w i , w j μ ( w ) = w d μ ( d w ) i = 1 n d i = 1 m d φ ( i d ) φ ( j d ) \sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{i=1}^{\lfloor\frac{m}{d}\rfloor}\varphi(id)\varphi(jd)[gcd(i,j)=1]\\ =\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{i=1}^{\lfloor\frac{m}{d}\rfloor}\varphi(id)\varphi(jd)\sum_{w|i,w|j}\mu(w)\\ = \sum_{w|d}\mu(\frac{d}{w})\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{i=1}^{\lfloor\frac{m}{d}\rfloor}\varphi(id)\varphi(jd)

然后我们将原式更换枚举顺序,可以得到:
= d = 1 n w d w φ ( w ) μ ( d w ) i = 1 n d φ ( i d ) j = 1 m d φ ( j d ) =\sum_{d=1}^n\sum_{w|d}\frac{w}{\varphi(w)} \mu(\frac{d}{w})\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\varphi(id)\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\varphi(jd)

然后我们令 f ( n ) = d n d φ ( d ) μ ( n d ) f(n)=\sum_{d|n}\frac{d}{\varphi(d)}\mu(\frac{n}{d}) g ( n , d ) = i = 1 n φ ( i d ) g(n,d)=\sum_{i=1}^n\varphi(id) ,原式就可以写成:
= d = 1 n f ( d ) g ( n d , d ) g ( m d , d ) =\sum_{d=1}^nf(d)g(\lfloor\frac{n}{d}\rfloor,d)g(\lfloor\frac{m}{d}\rfloor,d)

那么我们可以先线性筛出 φ ( i ) , μ ( i ) \varphi(i),\mu(i) ,然后枚举因子和倍数(类似诶氏筛的方式) O ( n l o g n ) O(nlogn) 的筛出 f ( i ) , g ( i , j ) f(i),g(i,j) ,其中 g ( i , j ) = g ( i 1 , j ) + φ ( i j ) g(i,j)=g(i-1,j)+\varphi(ij) i n j i\leq \frac{n}{j} ,但是每次回答还是要 O ( n ) O(n) ,所以我们这里采用分块打表的技巧,我们令答案 T ( n , x , y ) = i = 1 n f ( i ) g ( x , i ) g ( y , i ) T(n,x,y)=\sum_{i=1}^nf(i)g(x,i)g(y,i) ,我们预处理处 x , y 100 x,y\leq 100 左右的答案,复杂度为 O ( 100 × 101 2 × i = 1 n n i ) O(\frac{100\times 101}{2}\times \sum_{i=1}^n\frac{n}{i}) ,如果觉的常数大就可以少预处理一点。然后每次回答的时候,对于 i , j i,j 小于 m 100 \frac{m}{100} 的部分我们直接暴力算,而大于的部分我们已经预处理出来了,直接分块算,每次询问的复杂度为 O ( m + m 100 ) O(\sqrt{m}+\frac{m}{100}) 就可以过了。

空间上不要直接开满,用不定长数组 v e c t o r vector 可以节省大量空间。

常数炒鸡大和炒鸡丑陋的代码:

#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=1e5+10,N=101,W=1e5;
const int Mod=998244353;
ll prime[M],phi[M],mu[M],cnt;
ll F[M],inv[M];
vector <ll> T[N][N],G[M];
bool vis[M];
void init(){
	inv[0]=inv[1]=1;
	mu[1]=phi[1]=1;
	for(ll i=2;i<=W;i++){
		inv[i]=(Mod-Mod/i)*inv[Mod%i]%Mod;
		if(!vis[i]){
			prime[++cnt]=i;mu[i]=Mod-1;
			phi[i]=i-1;
		}
		for(ll j=1,v;j<=cnt&&i*prime[j]<=W;j++){
			v=i*prime[j];
			vis[v]=1;
			if(!(i%prime[j])){
				phi[v]=phi[i]*prime[j];
				break;	
			}
			mu[v]=(Mod-mu[i])%Mod;
			phi[v]=phi[i]*phi[prime[j]];
		}
	}
	for(ll i=1,v;i<=W;i++){
		v=inv[phi[i]]*i%Mod;
		for(int j=1;i*j<=W;++j){
			F[i*j]=(F[i*j]+v*mu[j]%Mod)%Mod;
		}
	}
	for(ll i=1;i<=W;i++){
		int L=W/i+1;G[i].push_back(0);
		for(ll j=1;j<L;j++){
			G[i].push_back((G[i][j-1]+phi[i*j])%Mod);
		}
	}
	for(int x=1;x<N;x++){
		for(int y=x;y<N;y++){
			int L=W/y+1;
			T[x][y].push_back(0);
			for(int i=1;i<L;i++){
				T[x][y].push_back((T[x][y][i-1]+F[i]*G[i][x]%Mod*G[i][y]%Mod)%Mod);
			}
		}
	}
}
int n,m;
ll ans;
void solve(){
	scanf("%d%d",&n,&m);
	ans=0;
	if(n>m)swap(n,m);
	int B=m/N;if(B>n)B=n;
	for(int i=1;i<=B;i++){
		ans=(ans+F[i]*G[i][n/i]%Mod*G[i][m/i]%Mod)%Mod;
	}
	for(int i=B+1,j;i<=n;i=j+1){
		j=min(n/(n/i),m/(m/i));
		ans=((ans+T[n/i][m/i][j])%Mod+Mod-T[n/i][m/i][i-1])%Mod;
	}
	printf("%lld\n",ans);
}
int Test;
int main(){
	init();
	for(scanf("%d",&Test);Test--;)solve();
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/VictoryCzt/article/details/85043474
今日推荐