教程讲解
欧拉筛
const int N = 1e5 + 10;
int prim[N], vis[N], len;
inline void eular_shai(int n) // n < N
{
for(int i = 2;i <= n;i ++)
{
if(! vis[i])
prim[len ++] = i;
for(int j = 0;j < len && i * prim[j] <= n; j ++)
{
vis[i * prim[j]] = 1;
if(i % prim[j] == 0)
break;
}
}
}j
欧拉函数
const int N = 1e5 + 10;
int phi[N], prim[N], vis[N], len;
void eular_fun(int n) //注意 n < N
{
phi[1] = 1;
for(int i = 2;i <= n; i ++)
{
if(! vis[i])
{
prim[len ++] = i;
phi[i] = i - 1; //因为欧拉函数代表小于这个数的且与这个数互质的数的个数,所以质数的欧拉函数为它本身减1
}
for(int j = 0; j < len && i * prim[j] <= n; j ++)
{
vis[i * prim[j]] = 1;
if(i % prim[j] == 0)
{
phi[i * prim[j]] = phi[i] * prim[j];
break;
}
else
{
phi[i * prim[j]] = phi[i] * (prim[j] - 1);
}
}
}
}
因子个数
原理: n = p 1 r 1 ∗ p 2 r 2 ∗ . . . ∗ p m r m n=p_1^{r1}*p_2^{r2}*...*p_m^{rm} n=p1r1∗p2r2∗...∗pmrm, 则 n 的因子个数为: ( p 1 + 1 ) ∗ ( p 2 + 1 ) ∗ . . . ∗ ( p n + 1 ) (p1+1)*(p2+1)*...*(pn+1) (p1+1)∗(p2+1)∗...∗(pn+1)
const int N = 1e5 + 10;
int prim[N], vis[N], d[N], sum[N], len;
// sum[i] 表示i的最小质因子的次方
// d[i] 表示 i 的约数的个数 -> 这个是我们的答案
void eular_num(int n)
{
d[1] = 1; //1 特判
for(int i = 2;i <= n;i ++)
{
if(! vis[i])
{
prim[len ++] = i;
sum[i] = 1;
d[i] = 2; //质数的约数只有1和它本身
}
for(int j = 0; j < len && i * prim[j] <= n; j ++)
{
vis[i * prim[j]] = 1;
if(i % prim[j] == 0)
{
sum[i * prim[j]] = sum[i] + 1;
d[i * prim[j]] = d[i] / (sum[i] + 1) * (sum[i] + 2);
break;
}
sum[i * prim[j]] = 1;
d[i * prim[j]] = d[i] * 2;
}
}
}
因子和
const int N = 1e5 + 10;
int prim[N], vis[N], psum[N], sum[N], len;
// sum[i] 表示i的最小质因子的次方
// d[i] 表示 i 的约数的个数 -> 这个是我们的答案
void eular_sum(int n) // n < N
{
sum[1] = 1; //注意这里根据题意赋值
for(int i = 2;i <= n;i ++)
{
if(! vis[i])
{
prim[len ++] = i;
psum[i] = sum[i] = i + 1;
}
for(int j = 0; j < len && i * prim[j] <= n;j ++)
{
vis[i * prim[j]] = 1;
if(i % prim[j] == 0)
{
psum[i * prim[j]] = psum[i] * prim[j] + 1;
sum[i * prim[j]] = sum[i] / psum[i] * psum[i * prim[j]];
break;
}
else
{
psum[i * prim[j]] = prim[j] + 1;
sum[i * prim[j]] = sum[i] * psum[i * prim[j]];
}
}
}
}