码迷,mamicode.com
首页 > 其他好文 > 详细

P1390 公约数的和

时间:2019-11-01 20:50:39      阅读:69      评论:0      收藏:0      [点我收藏+]

标签:scanf   turn   class   output   ons   lld   data-   int   math   

题目描述

有一天,TIBBAR和LXL比赛谁先算出1~N这N个数中每任意两个不同的数的最大公约数的和。LXL还在敲一个复杂而冗长的程序,争取能在100s内出解。而TIBBAR则直接想1s秒过而获得完胜,请你帮他完成这个任务。

输入格式

共一行,一个正整数N。

输出格式

共一行,一个数,为1~N这N个数中每任意两个不同的数的最大公约数的和。

输入输出样例

输入 #1
10
输出 #1
67

说明/提示

对于40%的数据,2≤N≤2000.

对于100%的数据,2≤N≤2000000.

思路

设f[d]=∑∑gcd(i,j)=d

F[d]=∑∑d|gcd(i,j)

不难看出F[d]=n/d*(n/d)

那么f[d]=F[d]-∑f[kd]

所以o(nlogn)扫一下就好了(主要是代码特别短)

然后ans=(∑f[d]-n*(n+1)/2)/2 减去gcd(d,d)=d的和gcd(i,j)=gcd(j,i)重复的

源自作者: Kelin

代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=2000010;

long long n,ans,f[N];

int main() {
	scanf("%lld",&n);
	for(long long i=n; i>0; i--) {//注意分母不为0!!!
		f[i]=n/i*(n/i);
		for(long long j=i<<1; j<=n; j+=i)
			f[i]-=f[j];
		ans+=f[i]*i;
	}
	printf("%lld\n",(ans-n*(n+1)/2)/2);
	return 0;
}

 

P1390 公约数的和

标签:scanf   turn   class   output   ons   lld   data-   int   math   

原文地址:https://www.cnblogs.com/mysh/p/11779196.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!