P2568 GCD(欧拉函数 || 反演)

时间:2021-03-10 05:18:04

题目描述

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

输入输出格式

输入格式:

一个整数N

输出格式:

答案

输入输出样例

输入样例#1: 复制
4
输出样例#1: 复制
4

说明

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

1<=N<=10^7


 


 


 


 

首先这个题可以用欧拉函数做:

这题嘛,首先我们枚举gcd(x,y)=p的p,那么gcd(x/p,y/p)肯定互质,也就是求在[1,n/p](向下取整)范围内的欧拉函数的前缀和,再乘2(因为x和y可以交换嘛),在减一,

 

然后也可以套反演 复杂度差不多是m×sqrt(n)

 

 


 


 


 


 

 

 1 #include <iostream>  2 #include"cmath"  3 #include"cstring"  4 #include"algorithm"  5 #include"stdio.h"  6 using namespace std;  7 typedef long long ll;  8  9 int mu[10000005]; 10 int prime[10000005]; int prime_c; 11 int vis[10000005]; 12 int sum[10000005]; 13 ll ans;int n; 14 15 void Mu() 16 { mu[1]=1; 17 for (int i=2;i<=10000000;i++) 18  { 19 if(!vis[i])mu[i]=-1,prime[++prime_c]=i; 20 for (int j=1;j<=prime_c;j++) 21  { 22 if(1ll*prime[j]*i>1ll*10000000)break; 23 vis[i*prime[j]]=1; 24 if(i%prime[j]==0)break; 25 mu[i*prime[j]]=-mu[i]; 26  } 27  } 28 29 for (int i=1;i<=10000000;i++)sum[i]=sum[i-1]+mu[i]; 30 31 // for (int i=1;i<=100;i++)cout<<mu[i]<<" "; 32 } 33 34 inline void work(int x) 35 { 36 int a=n; a/=x; 37 for (int r,l=1;l<=a;l=r+1) 38  { 39 r=a/(a/l); 40 ans+=1ll*(sum[r]-sum[l-1])*(a/l)*(a/l); 41  } 42 43 44 } 45 46 47 int main() 48 { cin>>n; 49  Mu(); 50 for (int j=1;j<=prime_c;j++) 51  { 52 int now=prime[j];if(now>n)break; 53  work(prime[j]); 54 // cout<<prime[j]<<" "<<ans<<endl; 55 56  } 57 58 cout<<ans; 59 60 61 }