您的位置:首页 > 其它

关于欧拉函数及Sicily1085的解法

2010-11-21 02:44 344 查看
1. 数论中的欧拉函数复习

F(x): 1~x中与x互质的数的个数,称为欧拉函数

欧拉函数是积性函数,即F(x*y)=F(x)*F(y),如果x和y互质

另外:F(x)=x-1,如果x是素数

F(xp)=xp-xp-1=xp-1*(x-1)

于是关于欧拉函数的求法如下:F(x)=F(x1p1*x2p2*...xnpn),然后采用上式求解

代码如下:

long long emular(int x)
{
long long ans=x;
int i;
for (i=0; i<MAXV; i++)
{
if (prime[i]>sqrt(1.0*x))
{
break;
}
if (x%prime[i]==0)
{
ans=ans/prime[i]*(prime[i]-1);
while (x%prime[i]==0)
{
x/=prime[i];
}
}
}
if (x>1)
{
ans=ans/x*(x-1);
}
return ans;
}


2. 关于Sicily1085

给定一个数N,要求1~N之间的每个数与N的最大公约数之和

算法:枚举每一个最大公约数i,求1~N之间与N的最大公约数是i的数的个数,设为p个,于是答案加上i×p

枚举的时候因为gcd(x,N)=i即等价于gcd(x/i,N/i)=1,于是等价于求解N/i的欧拉数,这样枚举i,加上i*(N/i)的欧拉数

参考代码如下:

#include <stdio.h>
#include <math.h>
#include <string.h>
const int MAXV = 1000020; //素数表范围
bool flag[MAXV+1]; //标志一个数是否为素数
int prime[MAXV+1]; //素数表,下标从0开始
int size; //素数个数
long long emular(int x) { long long ans=x; int i; for (i=0; i<MAXV; i++) { if (prime[i]>sqrt(1.0*x)) { break; } if (x%prime[i]==0) { ans=ans/prime[i]*(prime[i]-1); while (x%prime[i]==0) { x/=prime[i]; } } } if (x>1) { ans=ans/x*(x-1); } return ans; }
void genPrime(int max)
{
memset(flag, true, sizeof(flag));
for(int i = 2; i <= max / 2; i++)
{
if(flag[i])
{
for(int j = i << 1 ; j <= max; j += i)
{
flag[j] = false;
}
}
}
for(int i = 2 ; i <= max; i++)
{
if(flag[i])
{
prime[size++] = i;
}
}
//printf("%d/n",prime[size-1]);
}
int main()
{
int n;
long long i;
genPrime(655370);
while (scanf("%d",&n)!=EOF)
{
long long ans=0;
for (i=1;i<=sqrt(n*1.0);i++)
{
if (n%i==0)
{
ans=ans+i*emular(n/i);
if(n!=i*i)
ans=ans+(n/i)*emular(i);
}
}
printf("%lld/n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: