UVA 11426

UVA 11426(欧拉函数)

∑i=2N−1∑j=i+1Ngcd(i,j)\sum_{i=2}^{N-1}\sum_{j=i+1}^Ngcd(i,j)i=2N1j=i+1Ngcd(i,j)

一开始想过用莫比乌斯反演做…然而做不出来。

解:
∑i=1N−1∑j=i+1Ngcd(i,j)=∑i=2N∑j=1i−1gcd(i,j)\sum_{i=1}^{N-1}\sum_{j=i+1}^Ngcd(i,j)=\sum_{i=2}^N\sum_{j=1}^{i-1}gcd(i,j)i=1N1j=i+1Ngcd(i,j)=i=2Nj=1i1gcd(i,j)
gcd(i,j)=dgcd(i,j)=dgcd(i,j)=d等价于gcd(id,jd)=1gcd(\frac{i}{d},\frac{j}{d})=1gcd(di,dj)=1
既然直接求gcd(i,j)gcd(i,j)gcd(i,j)比较难,那么我们是否可以求满足[gcd(i,j)==1][gcd(i,j)==1][gcd(i,j)==1](i,j),j<i(i,j),j<i(i,j),j<i,这样每对(k∗i,k∗j)(k*i,k*j)(ki,kj)对答案的贡献就是kkk

因为jjj严格小于iiigcd(i,j)==1gcd(i,j)==1gcd(i,j)==1的个数就是ϕ(i)\phi(i)ϕ(i)
现在考虑kkk的取值范围,因为要满足1≤j<i≤n1\le j<i\le n1j<in,所以易得kkk的取值范围是1≤k≤⌊ni⌋1\le k\le \lfloor\frac{n}{i}\rfloor1kin

那么每个iii对答案的贡献就是1+2+...+⌊ni⌋1+2+...+\lfloor\frac{n}{i}\rfloor1+2+...+in

∑i=1N−1∑j=i+1Ngcd(i,j)=∑i=2N∑j=1i−1gcd(i,j)=∑i=2Nϕ(i)(1+⌊ni⌋)⌊ni⌋2\begin{aligned} \sum_{i=1}^{N-1}\sum_{j=i+1}^Ngcd(i,j)&=\sum_{i=2}^N\sum_{j=1}^{i-1}gcd(i,j)\\ &=\sum_{i=2}^N\phi(i)\frac{(1+\lfloor\frac{n}{i}\rfloor)\lfloor\frac{n}{i}\rfloor}{2} \end{aligned}i=1N1j=i+1Ngcd(i,j)=i=2Nj=1i1gcd(i,j)=i=2Nϕ(i)2(1+in)in

时间复杂度O(tn)+O(N)O(tn)+O(N)O(tn)+O(N)

#include<bits/stdc++.h>
using namespace std;
const int max_n=4e6+5;
int prime[max_n];
int vis[max_n];
int cnt=0;
int e[max_n];
void init(void)
{
	for(int i=2;i<max_n;i++)
	{
		if(!vis[i]){
			prime[cnt++]=i;
			e[i]=i-1;
		}
		for(int j=0;j<cnt&&i*prime[j]<max_n;j++)
		{
			vis[i*prime[j]]=1;
			if(i%prime[j]==0){
				e[i*prime[j]]=e[i]*prime[j];
				break;
			} 
			e[i*prime[j]]=e[i]*e[prime[j]];
		}
	}
}
int main(void)
{
	int n;
	init();
	while(~scanf("%d",&n)&&n)
	{
		long long ans=0,t;
		for(int i=2;i<=n;i++)
		{
			t=n/i;
			t=(1+t)*t/2;
			ans+=1ll*e[i]*t;
		}
		printf("%lld\n",ans);
	}
}
//10
//100
//200000
//0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值