2818: Gcd
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4363 Solved: 1919
[ 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
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
namespace Mobius_table{
const int MAX_N = 1e7;
int all=0;
int pr[MAX_N/10+100];
bool isp[MAX_N+10];
int mu[MAX_N+10];
/*****莫比乌斯函数分块打表前缀和*****/
int sum[MAX_N+10];
inline void init(){
memset(isp,0,sizeof(isp));
mu[1] = sum[1] = 1;
sum[0] = mu[0] = 0;
for(int i=2;i<=MAX_N;i++){
if(!isp[i]){
pr[all++]=i;
mu[i]=-1;
}
for(int j=0,k=pr[j]*i;k<=MAX_N;k=pr[++j]*i){
isp[k] = true;
if(i%pr[j]==0){
mu[k] = 0;
break;
}mu[k] = -mu[i];
}sum[i] = sum[i-1] + mu[i];
}
//printf("prime num = %d\n ",all);
}
}
using namespace Mobius_table;
inline long long work(int n){
long long res = 0;
for(int i=1,last;i<=n;i=last+1){
last = n/(n/i);
res += 1LL * (sum[last]-sum[i-1]) * (n/i) * (n/i);
}return res;
}
int main()
{
int n;init();
while(scanf("%d",&n)==1){
long long ans = 0;
for(int i=0;i<all&&pr[i]<=n;i++){
ans += work(n/pr[i]);
}printf("%lld\n",ans);
}return 0;
}