原题链接
poj
题意简述
多组数据。每次给定 n ( < = 1 e 6 ) n(<=1e6) n(<=1e6),求分子分母均是 < = n <=n <=n的正整数的真分数有多少个。(注释:真分数:满足1. 分子<分母 2. 分子和分母互质)
思路
这个怎么做呢?观察样例我们珂以有这样一个想法:枚举分母 i i i,然后求 [ 1 , i − 1 ] [1,i-1] [1,i−1]中有多少个和 i i i互质。
且慢。。。这不就是欧拉函数么???
也就是我们要求欧拉函数的前缀和。考虑到数据是
1
e
6
1e6
1e6而不是
1
e
9
1e9
1e9,我们珂以暴力求前缀和而不是杜教筛。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
namespace Flandle_Scarlet
{
#define N 1001000
#define int long long
int primes[N];
bool notp[N];
int phi[N];
void Init()
{
int n=1000000;
int &cnt=primes[0];
notp[1]=phi[1]=1;
for(int i=2;i<=n;++i)
{
if (!notp[i])
{
primes[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt and i*primes[j]<=n;++j)
{
int u=primes[j];
notp[i*u]=1;
if (i%u==0) {phi[i*u]=phi[i]*u;break;}
else phi[i*u]=phi[i]*phi[u];
}
}
for(int i=1;i<=n;++i)
{
phi[i]+=phi[i-1];
}
}
int n;
void Soviet()
{
printf("%lld\n",phi[n]-1);
}
void IsMyWife()
{
if (0)
{
freopen("","r",stdin);
freopen("","w",stdout);
}
Init();
while(~scanf("%lld",&n) and n)
{
Soviet();
}
}
#undef int //long long
};
int main()
{
Flandle_Scarlet::IsMyWife();
return 0;
}