题目链接:poj2478
题目大意:
给你一个数n,对于0 < a < b <= n,求真分数a/b的个数
即求n的欧拉函数前缀和(2<=n<=1e6)
思路;
欧拉函数:
积性函数筛:
需要处理三种情况
1. f(p),p是素数(直接等于素数的值减1)
2. f(p*i), 其中p不是i的约数,根据积性函数性质直接等于f(p)f(i) (即看上图片的第二条)
3. f(p*i), 其中p是i的约数,需要利用函数各自的性质 (即看上图片的第三条 f(i)*p)
该功能函数的代码;
int prime[100010],phi[1000010];
bool unprime[1000010];
__int64 sum[1000010];
void Euler()
{
int i,j,k = 0;
for(i = 2; i <= 1000000; i++)
{
if(!unprime[i])
{
prime[k++] = i;
phi[i] = i-1;//此处处理phi(p)
}
for(j = 0; j < k && prime[j]*i <= 1000000; j++)
{
unprime[prime[j] *i] = true;
if(i % prime[j] != 0)
{
//此处处理phi(i*p)=phi(i)*phi(p) ,p不是i的约数
//phi[prime[j]]==prime[j]-1
phi[prime[j]*i] = phi[i]*(prime[j]-1);
}
else
{
//此处处理phi(i*p),p是i的约数
phi[prime[j]*i] = phi[i]*prime[j];
break;
}
}
}
}
A代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<map>
using namespace std;
#define maxn 1000050
int prime[100010],phi[1000010];
bool unprime[1000010];
__int64 sum[1000010];
void Euler()
{
int i,j,k = 0;
for(i = 2; i <= 1000000; i++)
{
if(!unprime[i])
{
prime[k++] = i;
phi[i] = i-1;//此处处理phi(p)
}
for(j = 0; j < k && prime[j]*i <= 1000000; j++)
{
unprime[prime[j] *i] = true;
if(i % prime[j] != 0)
{
//此处处理phi(i*p)=phi(i)*phi(p) ,p不是i的约数
//phi[prime[j]]==prime[j]-1
phi[prime[j]*i] = phi[i]*(prime[j]-1);
}
else
{
//此处处理phi(i*p),p是i的约数
phi[prime[j]*i] = phi[i]*prime[j];
break;
}
}
}
}
int main()
{
int i,n;
Euler();
for(i = 1; i <= 1000000; i++)
sum[i] = sum[i-1] + phi[i];
while(~scanf("%d",&n) && n)
{
printf("%I64d\n",sum[n]);
}
return 0;
}