bzoj2818

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

這題看上去一點思路都沒有,但是如果我們從枚舉質數角度來考慮,那麼就是求gcd(i,j)=p的對數(1<=i<=n,1<=j<=n),那麼我們完全可以把n/p,然後就gcd(i,j)=1的對數,對於每個p,答案極爲mu(k)*[n/k]^2,由於n/k只有根號n種取值,所以對於每個p可以用根號n的時間求出對應的答案,那麼枚舉p的效率是n/ln(n),那麼這樣的複雜度就是n^1.5/ln(n),然後我們發現n/p的數的種類是根號級別的所以這題複雜度就是O(n)。


#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 10000005;
int mu[MAXN], prim[MAXN / 10], cnt;
bool f[MAXN];
int i, n, m, j, k, l;
long long ans;
inline long long getans(int n)
{
	long long tot = 0;
	for(int i = 1; i <= n;)
	{
		int j = n / i;
		int y = n / j, x = i;
		if (x > y) swap(x, y);
		tot += (mu[y] - mu[x - 1]) * j * (long long)j;
		i = y + 1;
	}
	return tot;
}
int main()
{
	mu[1] = 1;
	cin >> n;
	for(i = 2; i <= n; i ++)
	{
		if (!f[i])
		{
			prim[++cnt] = i;
			mu[i] = -1;
		}
		for(j = 1; j <= cnt && prim[j] * i <= n; j ++)
		{
			f[i * prim[j]] = 1;
			if (i % prim[j]) mu[i * prim[j]] = -mu[i];
			else {mu[i * prim[j]] = 0; break;}
		}
	}
	for(i = 2; i <= n; i ++)
		mu[i] += mu[i - 1];
	int p = 1;
	for(i = 1; i <= cnt; i ++)
	{
		if (i != cnt && n / prim[i] == n / prim[i + 1]) p ++;
		else ans += p * getans(n / prim[i]), p = 1;
	}
	cout << ans << endl;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章