您的位置:首页 > 其它

【bzoj2818】Gcd 欧拉函数

2016-11-21 13:06 435 查看

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2818

【题解】 

用f[i]表示1~i中gcd(a,b)=1的数对(a,b)的对数,那么显然 f[i] = 1+2* sigma(phi[j])  1<j<=i

那么ans = sigma(f[N/p])  p为小于N的素数

原理很简单,即如果gcd(a,b)=1,那么gcd(a*p,b*p)=p

 
/*************
bzoj 2818
by chty
2016.11.3
*************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAXN 10000010
int n,cnt,prime[MAXN],check[MAXN],phi[MAXN];
long long f[MAXN],ans;
inline int read()
{
int x=0,f=1;  char ch=getchar();
while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
return x*f;
}
void get()
{
phi[1]=1;
for(int i=2;i<=n;i++)
{
if(!check[i])  {prime[++cnt]=i;  phi[i]=i-1;}
for(int j=1;j<=cnt&&prime[j]*i<=n;j++)
{
check[i*prime[j]]=1;
if(i%prime[j])  phi[i*prime[j]]=phi[i]*(prime[j]-1);
else {phi[i*prime[j]]=phi[i]*prime[j];  break;}
}
}
}
int main()
{
freopen("cin.in","r",stdin);
freopen("cout.out","w",stdout);
n=read();
get();
f[1]=1;
for(int i=2;i<=n;i++)  f[i]=f[i-1]+2*phi[i];
for(int i=1;i<=cnt;i++)
if(prime[i]<n)  ans+=f[n/prime[i]];
printf("%lld\n",ans);
return 0;
}


 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: