运用线性筛
//若p是x的约数,则E(x*p)=E(x)*p.
//若p不是x的约数,则E(x*p)=E(x)*E(p)=E(x)*(p-1).
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int MAXN=3000001;
int prime[MAXN];//保存素数
bool vis[MAXN];//初始化
int phi[MAXN];//欧拉函数
void Prime(int n)
{
int cnt=0;
memset(vis,0,sizeof(vis));
for(int i=2;i<n;i++)
{
if(!vis[i])
{
prime[cnt++]=i;
phi[i]=i-1;// if p is prime,then phi[i]=i-1
}
for(int j=0;j<cnt&&i*prime[j]<n;j++)
{
__int64 k=i*prime[j];
vis[k]=1;
if(i%prime[j]==0)//关键
{
phi[k]=phi[i]*prime[j];
break;
}
else
phi[k]=phi[i]*(prime[j]-1);
}
}
}
int main()
{
int a,b;
Prime(3000000);
while(cin>>a>>b)
{
__int64 ans=0;
for(int i=a;i<=b;i++)
ans+=phi[i];
cout<<ans<<endl;
}
}
例题:HDU3501
题目大意:给你一个N,求小于等于N的不互质的数的总和。
欧拉公式的引伸:小于或等于n的数中,与n互质的数的总和为:φ(x) * x / 2。(n>1)
所以:res = n*(n-1)/2-n - phi[x]*x/2。
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
int eular(LL n) //欧拉函数
{
int i, ans = n;
for(i = 2; i * i <= n; i++)
{
if(n%i == 0)
{
ans -= ans/i;
while(n%i == 0)
n /= i;
}
}
if(n > 1) ans -= ans/n;
return ans;
}
int main()
{
LL n, ans;
while(scanf("%lld", &n), n)
{
ans = n * (n+1) / 2 - n; //总和
ans -= eular(n) * n / 2; //减去互质的总和公式
ans %= 1000000007; //再取模
printf("%lld
", ans);
}
return 0;
}