[pe530]GCD of Divisors

题目链接

https://projecteuler.net/problem=530

Solution

推式子+欧拉反演

[egin{aligned} ans&=sum_{i=1}^{n}sum_{jmid i}gcd(j,frac{i}{j})\ &=sum_{i=1}^{sqrt n}sum_{jmid i}sum_{kmid j,kmid frac{i}{j}}varphi(k)\ &=sum_{k=1}^{sqrt n}varphi(k)sum_{k|i,k|j}[ijle n]\ &=sum_{k=1}^{sqrt n}varphi(k)sum_{i,jge 1}[ijle frac{n}{k^2}]\ &=sum_{k=1}^{sqrt n}varphi(k)sum_{i=1}^{frac{n}{k^2}}lfloorfrac{frac{n}{k^2}}{p} floor end{aligned} ]

然后就大力求就好了。再算一下复杂度:

[egin{aligned} T(n)&=sqrt n imes sum_{k=1}^{sqrt n} k^{-1}\ &=sqrt n imes lnsqrt n end{aligned} ]

大概可以在 ([1s,10s]) 之间内得出答案。

然后我的程序跑了13s

这里是跑了3013s的code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int MAXN=300005;
const ll mod=1e9+7;
const ll inv2=mod-mod/2;
const ll inv6=166666668;
template <typename T>
void read(T &x) {
	T flag=1;
	char ch=getchar();
	for (; '0'>ch||ch>'9'; ch=getchar()) if (ch=='-') flag=-1;
	for (x=0; '0'<=ch&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
	x*=flag;
}
ll a, b;
ll prime[40000005], phi[40000005];
int cnt;
bool mark[40000005];
int T;
ll n;
void sieve() {
	phi[1]=1;
	for (int i=2; i<=40000000; i++) {
		if (!mark[i]) {
			prime[++cnt]=i;
			phi[i]=i-1;
		}
		for (int j=1; j<=cnt&&prime[j]*i<=40000000; j++) {
			mark[prime[j]*i]=true;
			if (i%prime[j]==0) {
				phi[i*prime[j]]=phi[i]*prime[j];
			} else {
				phi[i*prime[j]]=phi[i]*(prime[j]-1);
			}
		}
	}
}
int main() {
	sieve();
	read(n);
	ll x=sqrt(n), ans=0;
	for (ll i=1; i<=x; i++) {
		ll lim=n/(i*i);
		for (ll j=1, k; j<=lim; j=k+1) {
			k=lim/(lim/j);
			ans+=phi[i]*(k-j+1)*(lim/j);
		}
	}
	printf("%lld
", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/zcr-blog/p/14423056.html