您的位置:首页 > 其它

BZOJ-2818-Gcd(欧拉函数/Mobius反演)

2016-05-06 19:28 477 查看

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

首先欧拉函数:

小推一下公式:

Ans=prime(p)sigma(n,x=1)sigma(n,y=1)gcd(x,y)=p

=prime(p)sigma(n/p,x=1)sigma(n/p,y=1)gcd(x,y)=1

显然,预先累加处理一下欧拉函数phi[i]表示i内(x,y)互质对数,然后枚举n的质因子p,累加就可以了,

但是注意此题答案无序,而预先处理出的是有序的,所以需要乘2再减掉重复的形如(3,3)的就好。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define LL long long
#define bug cout<<"bug\n"
using namespace std;
const int MAXN = 1e7+7;
const int MAXM = 1e9+7;
long long phi[MAXN];
long long prime[MAXN];
int num_prime;
void get_euler(int n)
{
num_prime=0;
memset(phi,0,sizeof(phi));
phi[1]=0;
for(long long i=2; i<=n; ++i)
if(!phi[i])
{
prime[num_prime++]=i;
for(long long j=i; j<=n; j+=i)
{
if(!phi[j])
phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}
}
int main()
{
long long n;
//get_euler();
scanf("%I64d",&n);
{
get_euler(n);
long long ans=0;
for(int i=2; i<=n; ++i)
phi[i]+=phi[i-1];
for(int i=0; i<num_prime; ++i)
ans+=phi[n/prime[i]];
ans=ans*2+num_prime;
printf("%lld\n",ans);
//cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: