题外话:(我只是不知道该放哪才写在这的)
约数的个数 即求正整数 $n$ 的正约数个数
对于 $n$ 有唯一分解式 $n=p_1^{a_1} \, p_2^{a_2} \, p_3^{a_3}···p_k^{a_k}$
而对于任意一个质因子 $p_i$ ,在约数中的指数可以是 $0,1,2,3,...,a_i$ 共 $a_i+1$ 种情况,而且不同的素数因子间相互独立
所以 $n$ 的正约数个数为 $$f(n)= prod_{i=1}^k (a_i+1)$$
正题:
欧拉函数 是小于 $n$ 的正整数中与 $n$ 互质的数的个数,规定 $varphi (1)=1$
还是这个分解式 $n=p_1^{a_1} \, p_2^{a_2} \, p_3^{a_3}···p_k^{a_k}$
通式(很好记就不证明了逃) $$varphi (n)=n prod_{i=1}^k (1- frac{1}{p_i})$$
于是可以 $O(n)$ 求出欧拉函数
int euler(int n){ int ans=n; for (int i=2;i<=sqrt(n);i++) if (n%i==0){ ans=ans/i*(i-1); while(n%i==0) n/=i; } if(n>1) ans=ans/n*(n-1); return ans; }
如果是要求出 $1 sim n$ 所有的欧拉函数值 不需要用上面的方法做 $n$ 次
可以像下面这样做 时间复杂度 大概线性筛?
void euler_table(){ phi[1]=1; for(int i=2;i<=n;i++) if(!phi[i]) for(int j=i;j<=n;j+=i){ if(!phi[j]) phi[j]=j; phi[j]=phi[j]/i*(i-1); } }
这是一道关于欧拉函数的题 仪仗队
分析:以左下角为坐标原点 观察可知图是对称的 所以可以先分析对称轴下面一侧 即x>y 对于一个学生(x,y) 若x,y互质 则该同学可以被看到 若x,y不互质 则x,y至少有一个非1公因子k 于是(x,y)可以写成(kx',ky') 说明学生(x,y)一定会被学生(x',y')挡住 所以对于横坐标为x的学生 可以被看到的学生有φ(x)个 把所有φ值加起来就是一侧的人数 最后记得对称轴上还有一个
#include <cstdio> #include <algorithm> #include <cmath> using namespace std; #define N 50000 int n,ans=0; int phi[N+5]={0}; void euler(){ phi[1]=1; for(int i=2;i<=n;i++) if(!phi[i]) for(int j=i;j<=n;j+=i){ if(!phi[j]) phi[j]=j; phi[j]=phi[j]/i*(i-1); } } int main(){ scanf("%d",&n); n--; euler(); for(int i=1;i<=n;i++) ans+=phi[i]; if(!n) printf("0"); else printf("%d ",2*ans+1); return 0; }