BZOJ2705: [SDOI2012]Longge的问题

BZOJ2705: [SDOI2012]Longge的问题

Description

Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N)。

Input

一个整数,为N。

Output

一个整数,为所求的答案。

Sample Input

6

Sample Output

15

HINT

【数据范围】
对于60%的数据,0<N<=2^16。
对于100%的数据,0<N<=2^32。


题解Here!
题目要求:$Ans=\sum_{i=1}^ngcd(i,n)$
这式子好眼熟啊——莫比乌斯反演。
然而只有一个求和符号。
那就习惯性地枚举$gcd(i,n)$!
即:$$Ans=\sum_{d|n}\sum_{i=1}^nd[gcd(i,n)==d]$$
提到前面来:$$Ans=\sum_{d|n}d\sum_{i=1}^n[gcd(i,n)==d]$$
把那个$d$同时消去:$$Ans=\sum_{d|n}d\sum_{i=1}^{\frac{n}{d}}[gcd(i,\frac{n}{d})==1]$$
由于$d|n$,所以$d$与$\frac{n}{d}$的性质是一样的,于是:$$Ans=\sum_{d|n}d\sum_{i=1}^d[gcd(i,d)==1]$$
我们要求小于$d$且与$d$互质的数的个数。
这是什么?
$\varphi(i)$函数!
于是:$$Ans=\sum_{d|n}d\times \varphi(d)$$
然而这次$N<=2^{32}$,所以不能线性筛了,只能暴力$O(\sqrt n)$枚举因数。
前面那个也是暴力$O(\sqrt n)$枚举因数。
所以总复杂度的 上界是$O(n)$。
但是这个上界非常的松,所以总复杂度基本上也就$O(5\times 10^6)$的样子。。。
然后网上一堆神题解啊,本蒟蒻还是菜啊。。。
什么懵逼钨丝反演,甚至连$O(\sqrt n)$的算法,以及用$Pollard-rho$优化达到$O(\sqrt[4]n)$的算法都搞出来了。。。
真是百花齐放百家争鸣啊。。。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
inline long long read(){
	long long date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
long long phi(long long n){
	long long ans=n;
	for(long long i=2LL;i*i<=n;i++)
	if(n%i==0){
		ans=ans/i*(i-1);
		while(n%i==0)n/=i;
	}
	if(n>1)ans=ans/n*(n-1);
	return ans;
}
long long solve(long long n){
	long long ans=0,x=1LL;
	for(;x*x<n;x++)if(n%x==0)ans+=x*phi(n/x)+(n/x)*phi(x);
	if(x*x==n)ans+=x*phi(x);
	return ans;
}
int main(){
	long long n=read();
	printf("%lld\n",solve(n));
    return 0;
}
 

猜你喜欢

转载自www.cnblogs.com/Yangrui-Blog/p/9508661.html