【BZOJ3512】DZY Loves Math IV

题目大意

给出 n , m n,m n,m,求 ∑ i = 1 n ∑ j = 1 m ϕ ( i j ) \sum\limits_{i=1}^n\sum\limits_{j=1}^m\phi(ij) i=1nj=1mϕ(ij)

1 ≤ n ≤ 1 0 5 , 1 ≤ m ≤ 1 0 9 1\leq n\leq 10^5,1\leq m\leq 10^9 1n105,1m109,答案模 1 0 9 + 7 10^9+7 109+7


题解

前置知识:杜教筛

因为 n n n比较小,所以我们可以直接枚举 n n n

f ( n , m ) = ∑ i = 1 m ϕ ( n i ) f(n,m)=\sum\limits_{i=1}^m\phi(ni) f(n,m)=i=1mϕ(ni)

n n n分为若干个质数的乘积, n = p 1 a 1 p 2 a 2 ⋯ p k a k n=p_1^{a_1}p_2^{a_2}\cdots p_k^{a_k} n=p1a1p2a2pkak,令 p = p 1 a 1 − 1 p 2 a 2 − 1 ⋯ p k a k − 1 p=p_1^{a_1-1}p_2^{a_2-1}\cdots p_k^{a_k-1} p=p1a11p2a21pkak1 q = n / p q=n/p q=n/p

∑ i = 1 m ϕ ( n i ) = ∑ i = 1 m p ϕ ( q i ) = ∑ i = 1 m p ϕ ( q gcd ⁡ ( q , i ) × i ) × gcd ⁡ ( q , i ) \sum\limits_{i=1}^m\phi(ni)=\sum\limits_{i=1}^mp\phi(qi)=\sum\limits_{i=1}^mp\phi(\dfrac{q}{\gcd(q,i)}\times i)\times \gcd(q,i) i=1mϕ(ni)=i=1m(qi)=i=1m(gcd(q,i)q×i)×gcd(q,i)

因为 ϕ ( i ) \phi(i) ϕ(i)积性函数,所以 ϕ ( q gcd ⁡ ( q , i ) × i ) = ϕ ( q gcd ⁡ ( q , i ) ) × ϕ ( i ) \phi(\dfrac{q}{\gcd(q,i)}\times i)=\phi(\dfrac{q}{\gcd(q,i)})\times\phi(i) ϕ(gcd(q,i)q×i)=ϕ(gcd(q,i)q)×ϕ(i),原式变为

p ∑ i = 1 m ϕ ( q gcd ⁡ ( q , i ) ) × ϕ ( i ) × gcd ⁡ ( q , i ) p\sum\limits_{i=1}^m\phi(\dfrac{q}{\gcd(q,i)})\times\phi(i)\times \gcd(q,i) pi=1mϕ(gcd(q,i)q)×ϕ(i)×gcd(q,i)

欧拉函数的性质 n = ∑ d ∣ n ϕ ( n d ) n=\sum\limits_{d|n}\phi(\dfrac nd) n=dnϕ(dn),可得

p ∑ i = 1 m ϕ ( i ) ϕ ( q gcd ⁡ ( q , i ) ) ∑ j ∣ i , j ∣ q ϕ ( gcd ⁡ ( q , i ) j ) p\sum\limits_{i=1}^m\phi(i)\phi(\dfrac{q}{\gcd(q,i)})\sum\limits_{j|i,j|q}\phi(\dfrac{\gcd(q,i)}{j}) pi=1mϕ(i)ϕ(gcd(q,i)q)ji,jqϕ(jgcd(q,i))

因为 q gcd ⁡ ( q , i ) \dfrac{q}{\gcd(q,i)} gcd(q,i)q gcd ⁡ ( q , i ) \gcd(q,i) gcd(q,i)互质( q = p 1 p 2 ⋯ p k q=p_1p_2\cdots p_k q=p1p2pk,同一个质数要不不出现,要不出现在 q gcd ⁡ ( q , i ) \dfrac{q}{\gcd(q,i)} gcd(q,i)q gcd ⁡ ( q , i ) \gcd(q,i) gcd(q,i),不可能两个都出现)而 ϕ \phi ϕ积性函数,所以 ϕ ( q gcd ⁡ ( q , i ) ) × ϕ ( gcd ⁡ ( q , i ) j ) = ϕ ( q j ) \phi(\dfrac{q}{\gcd(q,i)})\times \phi(\dfrac{\gcd(q,i)}{j})=\phi(\dfrac qj) ϕ(gcd(q,i)q)×ϕ(jgcd(q,i))=ϕ(jq),可得

p ∑ i = 1 m ϕ ( i ) ∑ j ∣ i , j ∣ q ϕ ( q j ) p\sum\limits_{i=1}^m\phi(i)\sum\limits_{j|i,j|q}\phi(\dfrac qj) pi=1mϕ(i)ji,jqϕ(jq)

枚举 j j j

p ∑ j ∣ q ϕ ( q j ) ∑ i = 1 ⌊ m j ⌋ ϕ ( i j ) p\sum\limits_{j|q}\phi(\dfrac qj)\sum\limits_{i=1}^{\lfloor\frac mj\rfloor}\phi(ij) pjqϕ(jq)i=1jmϕ(ij)

因为 f ( n , m ) = ∑ i = 1 m ϕ ( n i ) f(n,m)=\sum\limits_{i=1}^m\phi(ni) f(n,m)=i=1mϕ(ni),所以

p ∑ j ∣ q ϕ ( q j ) × f ( j , ⌊ m j ⌋ ) p\sum\limits_{j|q}\phi(\dfrac qj)\times f(j,\lfloor\dfrac mj\rfloor) pjqϕ(jq)×f(j,jm⌋)

于是我们就得到了递推式

f ( n , m ) = p ∑ j ∣ q ϕ ( q j ) × f ( j , ⌊ m j ⌋ ) f(n,m)=p\sum\limits_{j|q}\phi(\dfrac qj)\times f(j,\lfloor\dfrac mj\rfloor) f(n,m)=pjqϕ(jq)×f(j,jm⌋)

预处理出前 n 2 3 n^{\frac 23} n32 ϕ ( i ) \phi(i) ϕ(i)并求前缀和,用杜教筛 ϕ ( i ) \phi(i) ϕ(i)的前缀和,利用 ϕ \phi ϕ的前缀和作差得出每个 ϕ ( q j ) \phi(\dfrac qj) ϕ(jq),然后就可以用杜教筛求 f ( n , m ) f(n,m) f(n,m)了。

注意 f ( n , m ) f(n,m) f(n,m)的一些特殊值。

  • n = 1 n=1 n=1时, f ( n , m ) = ∑ i = 1 m ϕ ( i ) f(n,m)=\sum\limits_{i=1}^m\phi(i) f(n,m)=i=1mϕ(i)
  • m = 1 m=1 m=1时, f ( n , m ) = ϕ ( n ) f(n,m)=\phi(n) f(n,m)=ϕ(n)

最终的答案为 ∑ i = 1 n f ( i , m ) \sum\limits_{i=1}^nf(i,m) i=1nf(i,m)

code

#include<bits/stdc++.h>
using namespace std;
const int N=2000000;
const long long mod=1000000007;
int z[N+5],p[N+5],mn[N+5];
long long ans,ph[N+5],s[N+5];
map<long long,long long>sph,sum[100005];
void init(){
	ph[1]=1;
	for(int i=2;i<=N;i++){
		if(!z[i]){
			p[++p[0]]=i;
			ph[i]=i-1;mn[i]=i;
		}
		for(int j=1;j<=p[0]&&i*p[j]<=N;j++){
			z[i*p[j]]=1;
			mn[i*p[j]]=p[j];
			if(i%p[j]==0){
				ph[i*p[j]]=ph[i]*p[j]%mod;
				break;
			}
			ph[i*p[j]]=ph[i]*(p[j]-1)%mod;
		}
	}
	for(int i=1;i<=N;i++){
		s[i]=(s[i-1]+ph[i])%mod;
	}
}
long long gt(int n){
	if(n<=N) return s[n];
	if(sph.count(n)) return sph[n];
	long long re=0;
	for(int l=2,r;l<=n;l=r+1){
		r=min(n,n/(n/l));
		re=(re+1ll*(r-l+1)*gt(n/l)%mod)%mod;
	}
	re=(1ll*n*(n+1)/2-re+mod)%mod;
	return sph[n]=re;
}
long long djs(int n,int m){
	if(!m) return 0;
	if(n==1) return gt(m);
	if(m==1) return ph[n];
	if(sum[n].count(m)) return sum[n][m];
	long long re=0;
	vector<int>v;
	int p=1,q=1,t=n,l=0;
	while(t>1){
		int x=mn[t];
		q*=x;t/=x;
		v.push_back(x);++l;
		while(t%x==0){
			p*=x;t/=x;
		}
	}
	for(int i=0;i<1<<l;i++){
		int vt=1;
		for(int j=0;j<l;j++)
		if(i&(1<<j)) vt*=v[j];
		re=(re+ph[q/vt]*djs(vt,m/vt)%mod)%mod;
	}
	return sum[n][m]=re*p%mod;
}
int main()
{
	int n,m;
	init();
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		ans=(ans+djs(i,m))%mod;
	}
	printf("%lld",ans);
	return 0;
}
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值