原网址:https://blog.csdn.net/Danliwoo/article/details/48827813#fermat
。。看不懂目前也不想去钻研,,
索性粘贴上看过的内容,留着用
void genPhi()
{
for(int i = 1;i < max;i++)
minDiv[i] = i;
for(int i = 2;i*i < max;i++)
{
if(minDiv[i] == i)
{
for(int j = i*i;j < max;j += i)
minDiv[j] = i;
}
}
phi[1] = 1;
for(int i = 2;i < max;i++)
{
phi[i] = phi[i/minDiv[i]];
if((i/minDiv[i]) % minDiv[i] == 0)
phi[i] *= minDiv[i];
else
phi[i] *= minDiv[i] - 1;
}
}
资料来源:https://blog.csdn.net/Danliwoo/article/details/48851073
真心看不明白,,又觉得讲得很好的样子。。
欧拉函数的证明以及应用(附POJ例题)
应用
POJ 2407
给n,求ϕ(n)ϕ(n)
按照欧拉函数公式分解出所有n的质因子即可计算得到答案。复杂度O(n−−√n)
int phi(int n)
{
int ans = n;
for(int 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;
}
POJ 1284
给素数p,求原根,即ϕ(p−1)ϕ(p−1)
关于原根的知识之后再补充。
POJ 2478
给n,求ans[n]。其中ans[n]=ans[n-1]+phi[n],且n的范围比较大,在10的6次以内。则考虑打表解决。
先得到能整除i的最小正整数md[i](一定是个素数),再利用性质3,得到phi[i]
void set()
{
for(int i = 0;i < N;i++)
md[i] = i;
for(int i = 2;i < N;i++) if(md[i] == i)
{ //也可以只让2和奇数进来
for(int j = i;j < N;j += i) if(md[j] == j)
md[j] = i; //只要最小的,不要被覆盖
}
for(int i = 2;i < N;i++)
{
if(md[i] == i)
phi[i] = i-1;
else
{
phi[i] = phi[i/md[i]];
if(i/md[i] % md[i])
phi[i] *= md[i]-1;
else
phi[i] *= md[i];
}
}
}
后面这种写法比较简短,也可以根据性质3来理解。
void set()
{
for(int i = 0;i < N;i++)
phi[i] = i;
for(int i = 2;i < N;i += 2)
phi[i] /= 2; //质数为2先处理一遍
for(int i = 3;i < N;i += 2) if(phi[i] == i)
{ //处理奇因子
for(int j = i;j < N;j += i)
phi[j] = phi[j]/i*(i-1);
}
}
POJ 3090
给n,求ans[i] = ans[i-1] + 2*phi[i]