P2568 GCD

看到这是一道紫题还是和gcd有关的才点进来(毕竟数论只会gcd).

  • 前置芝士(为了保证绝大多数人能看懂,有一些非常基础的前置芝士,如果已经了解可以pass)

    • 质数(又称素数):因数只有1和本身,但是很特殊的1不是一个质数.
    • gcd:欧几里得算法,又称辗转相除法,可以在约为O(LogN)的时间复杂度内求出两个数的最大公约数(N为两个数中大的那个数,在两数为相邻的斐波那契数时最慢,具体不证明其实就是我不会).
    • 欧拉函数:一个非常基本的数论函数,是一个积性函数(虽然本题并没有考到),欧拉函数可以表示为 φ ( x ) \varphi(x) φ(x),表示小于x的自然数中与x互质的数的个数(具体求法下文会讲到).
  • 推导公式

很明显,直接暴力需要O(N^2)的时间发咋读但是N有1e7肯定是会T的,所以需要从gcd(a,b)为一个质数入手.
g c d ( a , b ) = = 1 gcd(a,b)==1 gcd(a,b)==1时不难发现 g c d ( a ∗ p , b ∗ p ) = = p gcd(a*p,b*p)==p gcd(ap,bp)==p(p为任何自然数时都成立),于是乎可以先把0~N中的素数筛出来.
那么下面要怎么知道一个素数可以产生几对符合条件的a,b呢?
可以发现 m a x ( a , b ) ∗ p ≤ N ⇒ m a x ( a , b ) ≤ N p max(a,b)*p\leq N\Rightarrow max(a,b)\leq \dfrac {N}{p} max(a,b)pNmax(a,b)pN因为a,b都为整数,所以 m a x ( a , b ) ≤ ⌊ N p ⌋ max(a,b)\leq \lfloor\dfrac {N}{p}\rfloor max(a,b)pN,于是就要知道小于p的互质的数对的个数了,拿出前置芝士中的欧拉函数,于是小于p的数的对数 = 2 ∗ ∑ i = 1 ⌊ N p ⌋ φ ( i ) =2*\sum ^{\tiny\lfloor\dfrac {N}{p}\rfloor}_{i=1}\varphi \left( i\right) =2i=1pNφ(i)(因为如(1,2)和(2,1)同时成立,所以需要乘2),每次都要求自然还是会T,所以需要用到前缀和优化一下.

  • 具体实现

    • 欧拉函数的具体实现:(本人太菜,只会用埃氏筛)
      对于x不是质数 φ ( x ) = x ∗ ∏ i = 1 n ( 1 − 1 p i ) \varphi(x)=x*\prod ^{n}_{i=1}(1-\dfrac {1}{p_{i}}) φ(x)=xi=1n(1pi1)(其中 p i p_{i} pi为为x质因数,n为x的质因数的个数)
      x为质数时 φ ( x ) = x − 1 \varphi(x)=x-1 φ(x)=x1
      其中十分特殊的 φ ( 1 ) = 1 \varphi(1)=1 φ(1)=1
      这样可以直接套入埃氏筛中将所有 1 ≤ x ≤ N 1\leq x\leq N 1xN φ ( x ) \varphi(x) φ(x)求出,再用一个sum数组统计起来.
      如果还不是很了解可以康康例题.
  • 代码

#include<bits/stdc++.h>
#define rap(i,first,last) for(int i=first;i<=last;++i)
using namespace std;
const int maxN=1e7+5;
int N;
double phi[maxN];
bool boo[maxN];
long long sum[maxN];//注意开long long
int main()
{
	scanf("%d",&N);
	rap(i,1,N)
	{
		boo[i]=1;
		phi[i]=i;//先赋值为i方便处理
	}
	boo[1]=0;//不是质数
	rap(i,2,N)//埃氏筛的部分
	if(boo[i])
	{
		phi[i]=i-1;
		rap(j,2,N/i)
		{
			boo[i*j]=0;
			phi[i*j]*=1.0-1.0/i;//求出欧拉函数的值
		}
	}
	sum[1]=1;//1时因为只有(1,1)所以不用乘二
	rap(i,2,N)
	sum[i]=sum[i-1]+1ll*((int)phi[i])*2;//用前缀和优化
	long long answer=0;//注意long long
	rap(i,2,N)
	if(boo[i])answer+=sum[N/i];//把每个质数所带来的(a,b)全部相加
	printf("%lld",answer);//输出answer
	return 0;
}

数论题的题解好难写

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值