[Test-1.11]-T2divisor

Description:

给定整数 n,求:
(sum_{i=1}^n sum_{d|i}GCD(d, frac{i}{d}))
保证答案在 long long 范围内。

Solution:

莫比乌斯反演qvq,生搬硬套

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#define R register
#define ll long long
namespace IO
{
	template<class T>
	void rea(T &x)
	{
		char ch=getchar();int f(0);x = 0;
		while(!isdigit(ch)){f|=ch=='-';ch=getchar();}
		while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
		x = f?-x:x;
	}
	template<class T>
	T max(T a, T b) { return (a>b?a:b); }
	template<class T>
	T min(T a, T b) { return (a<b?a:b); }
}
using IO::rea;
using namespace std;
ll n, up, ans;
ll prime[5000005], tot, phi[5000005];
bool ban[5000005];
void getphi(ll p)
{
	phi[1] = 1;
	for(R int i = 2; i <= p; ++i)
	{
		if(!ban[i]) prime[++tot] = i, ban[i] = 1, phi[i] = i-1;
		for(R int j = 1; j <= tot; ++j)
		{
			if(i*prime[j] > p) break;
			ban[i*prime[j]] = 1;
			if(i % prime[j] == 0)
			{
				phi[i*prime[j]] = phi[i]*prime[j];
				break;
			}
			else phi[i*prime[j]] = phi[i]*phi[prime[j]];
		}
	}
	for(R int i = 1; i <= p; ++i) phi[i] = phi[i-1]+phi[i];
}
int main()
{
	freopen("divisors.in","r",stdin);
	freopen("divisors.out","w",stdout);
	using IO::max;using IO::min;
	rea(n);
	up = sqrt(n);
	getphi(up);
	int j;
	for(R int i = 1; i <= up; i = j)
	{
		for(j=i+1; n/(1ll*i*i) == n/(1ll*j*j) && j<=up;j++);
		ll temp = 0, u = n/(1ll*i*i);
		for(R ll x = 1; x <= u; ++x)
		{
			ll r = u/(u/x);
			temp += (u/x) * (min(r, u)-x+1);
			x = r;
		}
		ans += (phi[j-1]-phi[i-1])*temp;
	}
	cout<<ans<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/heanda/p/12405073.html