https://vj.xtuacm.cf/contest/view.action?cid=57#problem/I
1.当需要求1到N的欧拉数之和时用线性方法(本题)
2.当需要求单个欧拉数但数据很大用标准方法求
例如:https://vj.xtuacm.cf/contest/view.action?cid=57#problem/H
线性的方法求欧拉数代码(模板):
#include<stdio.h>
#include<string.h>
#define ll long long
const int MAXN=1000010;
int dp[MAXN];
ll a[MAXN];
int main()
{
memset(dp,0,sizeof(dp));
dp[1]=1;
for(int i=2; i<MAXN; i++)
{
if(dp[i])continue;
for(int j=i; j<MAXN; j+=i)
{
if(!dp[j])dp[j]=j;
dp[j]=dp[j]/i*(i-1);
}
}
a[1]=1;
a[2]=1;
for(int i=3;i<=MAXN;i++)
a[i]=a[i-1]+dp[i];
int N;
while(~scanf("%d",&N),N)
{
printf("%I64d\n",a[N]);
}
return 0;
}
普通方法求欧拉数:https://vj.xtuacm.cf/contest/view.action?cid=57#problem/H
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#define ll long long
using namespace std;
int a[4000],c[5000],d[40010];
int cnt;
void init()//筛选出质数
{
int num=0;
memset(d,1,sizeof(d));
for(int i=2;i<=40000;i++)
{
if(d[i])
{
for(int j=2*i;j<=40000;j=j+i)
d[j]=0;
c[num++]=i;
}
}
}
void fen(int n)//分解质因数
{
cnt=0;
for(int i=0;c[i]*c[i]<=n;i++)
{
if(n%c[i]==0)
{
a[cnt++]=c[i];
while(n%c[i]==0)
n=n/c[i];
}
}
if(n>1)
a[cnt++]=n;
}
int main()
{
init();
int n;
while(~scanf("%d",&n),n)
{
memset(a,0,sizeof(a));
fen(n);
int l=n;
for(int i=0;i<cnt;i++)//得出结果
l=l-l/a[i];
cout<<l<<endl;
}
return 0;
}