• 线性筛


    数论函数

    (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))

    [f(a)(b) \=sum_{u|a}usum_{v|b}v \=sum_{u|a}sum_{v|b}uv ]

    因为(a⊥b),所以(u⊥v)

    所以(ab)的因数一定是选 (一个a的因数 imes一个b的因数)

    所以上式可写为

    [=sum_{(uv)|(ab)}uv \=sum_{d|x}d ]

    利用积性函数的性质

    枚举(i)进行讨论:

    1. 质数的情况

    2. (i⊥p_j)的情况

    3. (p_j)(i)最小质因子的情况

    (1)(n)的约数个数函数(sigma^0)

    显然(sigma^0)(sigma)一样都是积性函数。

    [n=prod_{i=1}^k{p_i}^{c_i} (p_i是质数) ]

    通过小学奥数我们知道

    [sigma(n)=prod_{i=1}^k(c_i+1) ]

    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])

    [n=prod_{i=1}^k{p_i}^{c_i} (p_i是质数) ]

    通过容斥原理可得

    [varphi(n) \=prod_{i=1}^k(p_i-1)p_i^{c_i-1} \=nprod_{i=1}^k(1-frac{1}{p_i}) \ ]

    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的莫比乌斯函数(μ)

    [n=prod_{i=1}^k{p_i}^{c_i} (p_i是质数) ]

    (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):)

    1. 如果(mu(a) = 0)(mu(b)=0)。则(ab)必含平方因子
    2. 否则,由于(a⊥b)。所以(ab)不含平方因子,所

    [mu(a)mu(b)=(-1)^{k_a}(-1)^{k_b}=(-1)^{k_a+k_b}=mu(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}))的关系式。

  • 相关阅读:
    SQLServer执行大脚本文件时,提示“无法执行脚本没有足够的内存继续执行程序 (mscorlib)”
    SQLServer临时库文件太大,迁移tempdb数据库
    SQL Server设置数据库为状态为只读
    微信企业号应用
    前端不错的网站
    模拟桶排序
    记录javascript 验证字符串布尔类型 及url 参数获取
    JS表单设置值
    C#标准响应数据
    C# Like参数化 小记
  • 原文地址:https://www.cnblogs.com/oply/p/12737089.html
Copyright © 2020-2023  润新知