数论函数
(f(n)),定义域为(N)(正整数域),值域为(N)的函数。
常见:
(f(x) = x)
(f(x)=x^2)
(f(x)=sum_{i=1}^xi=frac{x(x+1)}{2})
(f(x)=sum_{i=0}^x2^i=2^{x+1}-1)
(f(x)=sum_{d|x}d)
积性函数
(f(x)),如果(forall a,b,a⊥b,ab=x,f(a)(b)=f(x)),则称(f)为积性函数。
比如:
(f(x)=x)
(f(x)=x^2)
(φ(x)) — 欧拉函数
(mu(x)) — 莫比乌斯函数
(gcd(x,k)) — (k)固定时的最大公因数
(σ(x)) — (x)的因数之和
(σ^0(x)) — (x)的因数个数
线性筛
找出(1)—(n)内的所有质数
Etratosthenes筛
开始认为所有数都是质数。暴力枚举每个数,如果是质数,就将它所有的倍数标为非质数。
bool is[N]; // 标记数组
int p[N], cn; // 质数数组
memset(is, 1, sizeof(is));
is[1] = 0;
for (int i = 2; i <= n; i++)
if (is[i])
{
p[++cn] = i;
for (int j = i * i; j <= n; j += i)
is[j] = 0;
}
时间复杂度(O(n log^2_n)),懒得写线性筛就写这玩意
线性筛
让每个数被其最小质因子筛掉,这样就可以实现每个数只被筛一次。
bool is[N]; // 标记数组
int p[N], cn; // 质数数组
memset(is, 1, sizeof(is));
is[0] = is[1] = 0;
for (int i = 2; i <= n; i++)
{
if (is[i]) p[++cn] = i;
for (int j = 1; j <= cn && i * p[j] <= n; j++)
{
is[i * p[j]] = 0;
if (i % p[j] == 0) break; // i已经包含p[j],继续枚举p[j]一定大于当前,不会是i*p[j]的最小质因子
}
}
求(1)—(n)的约数和函数(sigma)
(sigma (n))
证明:
考虑(a,b(a⊥b,ab=x))
因为(a⊥b),所以(u⊥v)。
所以(ab)的因数一定是选 (一个a的因数 imes一个b的因数)
所以上式可写为
利用积性函数的性质
枚举(i)进行讨论:
-
质数的情况
-
(i⊥p_j)的情况
-
(p_j)是(i)最小质因子的情况
求(1)—(n)的约数个数函数(sigma^0)
显然(sigma^0)和(sigma)一样都是积性函数。
设
通过小学奥数我们知道
bool is[N]; // 标记数组
int p[N], cn, g[N], f[N]; // g[x]表示x的最小质因子的次数
memset(is, 1, sizeof(is));
is[0] = is[1] = 0;
for (int i = 2; i <= n; i++)
{
if (is[i]) p[++cn] = i, g[i] = 1, f[i] = 1;
for (int j = 1; j <= cn && i * p[j] <= n; j++)
{
int x = i * p[j];
//p[j]为x的最小质因子
is[x] = 0;
if (i % p[j] == 0)
{
g[x] = g[i] + 1;
f[x] = f[i] * (g[x] + 1) / (g[i] + 1);
break;
}
else
g[x] = 1,
f[x] = f[i] * 2;
// i不是p[j]的倍数,互质
}
}
求1—n的欧拉函数(varphi)
(varphi(n) = sum_{i=1}^n[i⊥n])
设
通过容斥原理可得
bool is[N]; // 标记数组
int p[N], cn, f[N];
memset(is, 1, sizeof(is));
is[0] = is[1] = 0;
for (int i = 2; i <= n; i++)
{
if (is[i]) p[++cn] = i, f[i] = i - 1; // 质数时f[i]=i-1
for (int j = 1; j <= cn && i * p[j] <= n; j++)
{
int x = i * p[j];
//p[j]为x的最小质因子
is[x] = 0;
if (i % p[j] == 0)
{
f[x] = f[i] * p[j];
break;
}
f[x] = f[i] * f[p[j]];
// i不是p[j]的倍数,互质
}
}
求1—n的莫比乌斯函数(μ)
设
(mu(n)=egin{cases} 1& n=1 \ (-1)^k & n无平方数因数 \ 0 & otherwise end{cases})
(mu)是积性函数证明:
(forall a,b,a⊥b,ab=x)
(mu(a)(b):)
- 如果(mu(a) = 0)或(mu(b)=0)。则(ab)必含平方因子
- 否则,由于(a⊥b)。所以(ab)不含平方因子,所
bool is[N]; // 标记数组
int p[N], cn, f[N]; // 质数数组
memset(is, 1, sizeof(is));
is[0] = is[1] = 0;
for (int i = 2; i <= n; i++)
{
if (is[i]) p[++cn] = i, f[i] = -1; // 质数肯定标为-1
for (int j = 1; j <= cn && i * p[j] <= n; j++)
{
int x = i * p[j];
is[x] = 0;
if (i % p[j] == 0)
{
f[x] = 0; break; // x为(p[j]^2)的倍数,有平方因子
}
f[x] = -f[i]; // p[j]是质数,f[p[j]]=-1
}
}
一般积性函数
一个积性函数(f),可以考虑以下的线性筛法:
要计算(f(n)),考虑到(n=prod_{i=1}^k{p_i}^{c_i} (p_i是质数))
在线性筛的过程中,如果(i mod p_j e0),就有(f(ip_j)=f(i)f(p_j))
否则,考虑(k|(ip_j),k⊥p_j),则有(f(ip_j)=f(k)f(frac{ip_j}k))
因此,我们只需要记录对于每一个(ip_j)对应的(k),或者推导出(f(p^c))到(f(p^{c+1}))的关系式。