UVA11426 GCD - Extreme (II)

UVA11426 GCD - Extreme (II)

这几天我看了 LRJ 的书看到了这一题,就把这道题写了,正好这道题挺不错的。

题目

题目PDF

知识

欧拉函数

  • 定义: \(\varphi(n)\) 为小于等于 \(n\)\(n\) 互质的数的个数

它有一些有趣的性质:

  • \(\varphi(n)\) 是积性函数 : 如果有 \(\gcd(i,j) = 1\) 那么就有 \(\varphi(i \times j) = \varphi(i) \times \varphi(j)\)

如何求欧拉函数:

用一个类似于筛法求素数的方法,时间复杂度相似于埃氏筛法 \(\mathcal{O}(n\log \log n)\)

模板代码如下:

int phi[maxn];
void table(int n){
	for(int i = 0;i <= n;i ++)
        phi[i] = 0;
    phi[1] = 1;
    for(int i = 2;i <= n;i ++)
    	for(int j = i;j <= n;j ++){
    		if(!phi[j])		phi[j] = j;
    		phi[j] = phi[j] / i * (i-1);
    	}
   	return;
}

思路

首先,我们能想到暴力,每一次将每一个的 \(\gcd\) 求出 ,最差时间复杂度为 \(\mathcal{O}(n^2\log n )\) ,太慢,在这个数据目前无能为力,所以想办法优化。

\(\large f(n) = \sum\limits_{i=1}^{n-1}\gcd(i,n)\) ,所以答案为 \(\large S(n) = \sum\limits_{i=1}^{n} f(i)\)

易证\(\gcd(i,n)\) 的值都是 n 的约数,我们好好看看这个柿子有什么优化的地方

\(\dfrac{x}{i}\) ,所以 \(\gcd(\dfrac{x}{i},\dfrac{n}{i}) = 1\)

\(\therefore\) \(\dfrac{x}{i}\)\(\dfrac{n}{i}\) 互质

所以小于等于 \(\dfrac{n}{i}\) 的互质的 \(\dfrac{x}{i}\) 一共有 \(\varphi(\dfrac{n}{i})\)

\(\because\) \(\gcd(i,n)\) \(\leqslant n\)

$\therefore $ \(\large f(n) = \sum\limits_{i\subset A} i \times \varphi(\dfrac{n}{i})\) \(( A = n\) 的约数 \()\)

上面的柿子就是我们所需要的,时间复杂度与求欧拉筛法同阶。

代码 :

#include<cstdio>
#include<iostream>
#include<cstring>

using namespace std;
const int maxn = 4000000;

long long phi[maxn],s[maxn],f[maxn];

void phi_c(){
	for(int i=2;i<=maxn;i++)	phi[i] = 0;
	phi[1] = 1;
	for(int i=2;i<=maxn;i++){
		if(!phi[i])
		for(int j=i;j<=maxn;j+=i){
			if(!phi[j])
				phi[j] = j;
				phi[j] = phi[j] / i * (i-1);
		}
	}
}

int main()
{
	phi_c();
	memset(f,0,sizeof(f));
	for(int i=1;i<=maxn;i++)
		for(int j=i*2;j<=maxn;j+=i)
			f[j] += i*phi[j/i];
			
	s[2] = f[2];
	for(int j=3;j<=maxn;j++)
		s[j] = s[j-1] + f[j];
		
	int n;
	while(scanf("%d",&n) && n)
		printf("%lld\n",s[n]);
	return 0;
}
posted @ 2021-07-28 13:24  在那遥远的悠穹下  阅读(35)  评论(0编辑  收藏  举报