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

题目描述

给定整数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 }
原文地址:https://www.cnblogs.com/zhangbuang/p/10533333.html