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

bzoj 2818 Gcd

时间:2018-05-01 12:17:51      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:前缀和   一个   sea   mes   重复   php   oid   col   href   

2818: Gcd

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 7381  Solved: 3281
[Submit][Status][Discuss]

Description

给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.

 

Input

一个整数N

Output

如题

Sample Input

4

Sample Output

4

HINT

 

hint

对于样例(2,2),(2,4),(3,3),(4,2)


1<=N<=10^7

 

Source

总结:gcd(a, b) == c >>>>gcd(a / c, b / c) == 1;
然后想到枚举每个质数c,对欧拉函数求前缀和,
计数时要乘以2还要减去重复部分
两种情况:a / c > b / c, or a / c < b / c;
重复部分: a / c == b / c(应该减去)
 
#include<bits/stdc++.h>

using namespace std;

#define ll long long
const int maxn = 1e7 + 5;
int n, pri[maxn];
ll f[maxn];
bool Notpri[maxn]; int tot = 0;

void pre(int x) {
	f[1] = 1;
	for (int i = 2; i <= n; ++i) {
		if(!Notpri[i]) pri[++tot] = i, f[i] = i - 1;
		for (int j = 1; j <= tot && i * pri[j] <= n; ++j) {
			Notpri[i * pri[j]] = true;
			if(i % pri[j] == 0) {
				f[i * pri[j]] = f[i] * pri[j];
				break;
			} f[i * pri[j]] = f[i] * (pri[j] - 1);
		}
	}
	for (int i = 1; i <= n; ++i) f[i] += f[i - 1];
}

int main() {
	scanf("%d", &n);
	pre(n);
	ll ans = 0;
	for (int i = 1; i <= tot; ++i) {
		ans += f[n / pri[i]] * 2; ans--;
	} printf("%lld\n", ans);
	return 0;
}

  

bzoj 2818 Gcd

标签:前缀和   一个   sea   mes   重复   php   oid   col   href   

原文地址:https://www.cnblogs.com/oi-forever/p/8975661.html

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